import { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";

import { setLoading, setRefetching } from "@store/routesSlice";
import type { ReduxStateType } from "@store/types";
import type { FormattedQuoteResponse } from "./types";
import { useFetchQuotes } from "./useFetchQuotes";

export const useBestRoutes = () => {
	const dispatch = useDispatch();
	const [bestRoute, setBestRoute] = useState<FormattedQuoteResponse>();
	const [fastestRoute, setFastestRoute] = useState<FormattedQuoteResponse>();
	const refuelOpted = useSelector(
		(state: ReduxStateType) => state.quoteParams.addOnRefuel,
	);

	const {
		formattedAutoRoute,
		formattedManualRoutes,
		isLoading,
		isRefetching,
		data,
	} = useFetchQuotes();

	// This useEffect hook determines the best route based on the refuel option and output values.
	// It first checks if refuel is opted. If so, it prioritizes routes with refuel support.
	// If both routes support refuel, it compares their output values in USD to select the best one.
	// If only one route supports refuel, it selects that route.
	// If neither route supports refuel, it defaults to comparing the output values in USD.
	// The selected best route is then set using setBestRoute.
	// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
	useEffect(() => {
		const _bestManualRoute = formattedManualRoutes?.[0];

		// considering effective received value in usd
		const autoOutputInUsd =
			formattedAutoRoute?.primaryOutput?.effectiveReceivedInUsd ||
			formattedAutoRoute?.primaryOutput?.valueInUsd;
		const manualOutputInUsd =
			_bestManualRoute?.primaryOutput?.effectiveReceivedInUsd ||
			_bestManualRoute?.primaryOutput?.valueInUsd;

		const autoHasRefuel = formattedAutoRoute?.refuel;
		const manualHasRefuel = _bestManualRoute?.refuel;

		const autoEstimatedTime = formattedAutoRoute?.estimatedFulfilTime;
		const fastestManualRoute = formattedManualRoutes?.reduce((fastest, route) => {
			return route.estimatedFulfilTime < fastest.estimatedFulfilTime
				? route
				: fastest;
		}, formattedManualRoutes[0]);

		const compareRoutes = () => {
			if (autoOutputInUsd !== undefined && manualOutputInUsd !== undefined) {
				return autoOutputInUsd > manualOutputInUsd
					? formattedAutoRoute
					: _bestManualRoute;
			}
			return null;
		};

		const getBestRoute = () => {
			if (refuelOpted) {
				if (autoHasRefuel && manualHasRefuel) return compareRoutes();
				if (autoHasRefuel) return formattedAutoRoute;
				if (manualHasRefuel) return _bestManualRoute;
			}
			return compareRoutes() || _bestManualRoute;
		};

		const getFastestRoute = () => {
			// Determines the fastest route by comparing estimated times.
			// Prefers the auto route if times are equal and it has a higher output.
			if (
				autoEstimatedTime !== undefined &&
				fastestManualRoute?.estimatedFulfilTime !== undefined
			) {
				if (autoEstimatedTime < fastestManualRoute.estimatedFulfilTime) {
					return formattedAutoRoute;
				}
				if (autoEstimatedTime === fastestManualRoute.estimatedFulfilTime) {
					// If times are equal, compare the output values
					const manualOutputInUsd =
						fastestManualRoute?.primaryOutput?.effectiveReceivedInUsd ||
						fastestManualRoute?.primaryOutput?.valueInUsd;

					if (autoOutputInUsd !== undefined && manualOutputInUsd !== undefined) {
						return autoOutputInUsd >= manualOutputInUsd
							? formattedAutoRoute
							: fastestManualRoute;
					}
				} else {
					return fastestManualRoute;
				}
			}
			return autoEstimatedTime !== undefined
				? formattedAutoRoute
				: fastestManualRoute;
		};

		setBestRoute(getBestRoute() || formattedAutoRoute);
		setFastestRoute(getFastestRoute());
	}, [data]);

	useEffect(() => {
		dispatch(setLoading(isLoading));
		dispatch(setRefetching(isRefetching));

		if (isLoading) {
			setBestRoute(undefined);
		}
	}, [dispatch, isLoading, isRefetching]);

	return {
		bestRoute,
		fastestRoute,
		autoRoute: formattedAutoRoute,
		manualRoutes: formattedManualRoutes,
	};
};
