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

import { useTopRoutes } from "@hooks/apis/common/quote/useTopRoutes";
import { useTemporaryRoutingMode } from "@hooks/useTemporaryRoutingMode";
import { setOriginalRoutingMode, setRoutingMode } from "@store/settingsSlice";
import type { ReduxStateType } from "@store/types";
import { abbreviateNumber } from "@utils/abbreviateNumber";
import { Stars } from "../Icons";
import { MIcon } from "../MIcon";

type NotificationScenario =
	| "switched-to-manual"
	| "switched-to-auto"
	| "manual-selected-auto-better-return"
	| "auto-selected-manual-better-return"
	| "auto-no-routes-suggest-manual"
	| "manual-no-routes-suggest-auto"
	| null;

type TransactionSizeCategory = "small" | "medium" | "large";

const THRESHOLD_CONFIG: Record<
	TransactionSizeCategory,
	{ minDollar: number; minPercentage: number }
> = {
	small: { minDollar: 2, minPercentage: 1 }, // < $500
	medium: { minDollar: 10, minPercentage: 0.5 }, // $500-$5,000
	large: { minDollar: 25, minPercentage: 0.25 }, // > $5,000
};

const getTransactionSizeCategory = (
	inputValueInUsd: number,
): TransactionSizeCategory => {
	if (inputValueInUsd < 500) {
		return "small";
	}
	if (inputValueInUsd <= 5000) {
		return "medium";
	}
	return "large";
};

const meetsThreshold = (
	usdDifference: number,
	inputValueInUsd: number,
): boolean => {
	if (inputValueInUsd <= 0) return false;

	const category = getTransactionSizeCategory(inputValueInUsd);
	const threshold = THRESHOLD_CONFIG[category];

	const absoluteDifference = Math.abs(usdDifference);
	const percentageDifference = (absoluteDifference / inputValueInUsd) * 100;

	// Either dollar or percentage threshold must be met
	return (
		absoluteDifference >= threshold.minDollar ||
		percentageDifference >= threshold.minPercentage
	);
};

export const RouteModeNotification = () => {
	const dispatch = useDispatch();
	const routingMode = useSelector(
		(state: ReduxStateType) => state.settings.routingMode,
	);
	const originalRoutingMode = useSelector(
		(state: ReduxStateType) => state.settings.originalRoutingMode,
	);
	const { auto, manual } = useTopRoutes();
	const { isTemporarilySwitched, switchedToMode } = useTemporaryRoutingMode();
	const locale = useSelector(
		(state: ReduxStateType) => state.settings.language,
	);

	// Determine route availability
	const autoRoutesAvailable = useMemo(() => {
		return !!(auto.suggestedRoute || auto.maxOutputRoute || auto.fastestRoute);
	}, [auto]);

	const manualRoutesAvailable = useMemo(() => {
		return !!(manual.maxOutputRoute || manual.fastestRoute);
	}, [manual]);

	// Calculate USD value difference between auto and manual max output routes
	const usdDifference = useMemo(() => {
		const autoMaxOutput =
			auto.maxOutputRoute?.primaryOutput?.effectiveReceivedInUsd ||
			auto.maxOutputRoute?.primaryOutput?.valueInUsd ||
			0;
		const manualMaxOutput =
			manual.maxOutputRoute?.primaryOutput?.effectiveReceivedInUsd ||
			manual.maxOutputRoute?.primaryOutput?.valueInUsd ||
			0;

		return autoMaxOutput - manualMaxOutput;
	}, [auto.maxOutputRoute, manual.maxOutputRoute]);

	// Get input value in USD for threshold calculation
	const inputValueInUsd = useMemo(() => {
		return (
			auto.maxOutputRoute?.primaryInput?.valueInUsd ||
			manual.maxOutputRoute?.primaryInput?.valueInUsd ||
			0
		);
	}, [auto.maxOutputRoute?.primaryInput, manual.maxOutputRoute?.primaryInput]);

	// Determine which scenario to display
	const scenario: NotificationScenario = useMemo(() => {
		// Show switch suggestion when user is on a mode with no routes available and originalRoutingMode is null
		if (
			routingMode === "auto" &&
			!autoRoutesAvailable &&
			manualRoutesAvailable &&
			originalRoutingMode === null
		) {
			return "auto-no-routes-suggest-manual";
		}
		if (
			routingMode === "manual" &&
			!manualRoutesAvailable &&
			autoRoutesAvailable &&
			originalRoutingMode === null
		) {
			return "manual-no-routes-suggest-auto";
		}

		// Show switched notification if we switched and the condition that caused the switch is still true
		if (
			isTemporarilySwitched &&
			switchedToMode === "manual" &&
			!autoRoutesAvailable &&
			manualRoutesAvailable
		) {
			return "switched-to-manual";
		}
		if (
			isTemporarilySwitched &&
			switchedToMode === "auto" &&
			!manualRoutesAvailable &&
			autoRoutesAvailable
		) {
			return "switched-to-auto";
		}

		// Show better return notification for manual mode
		if (
			routingMode === "manual" &&
			manualRoutesAvailable &&
			autoRoutesAvailable &&
			usdDifference > 0
		) {
			return "manual-selected-auto-better-return";
		}

		// Show better return notification for auto mode (with threshold check)
		if (
			routingMode === "auto" &&
			manualRoutesAvailable &&
			autoRoutesAvailable &&
			usdDifference < 0 &&
			meetsThreshold(usdDifference, inputValueInUsd)
		) {
			return "auto-selected-manual-better-return";
		}

		return null;
	}, [
		routingMode,
		autoRoutesAvailable,
		manualRoutesAvailable,
		usdDifference,
		inputValueInUsd,
		isTemporarilySwitched,
		switchedToMode,
		originalRoutingMode,
	]);

	// Handle "Try Auto" button click
	const handleTryAuto = () => {
		dispatch(setRoutingMode("auto"));
		dispatch(setOriginalRoutingMode(null));
	};

	// Handle "Try Manual" button click
	const handleTryManual = () => {
		dispatch(setRoutingMode("manual"));
		dispatch(setOriginalRoutingMode(null));
	};

	// Don't render if no scenario applies
	if (!scenario) return null;

	const formattedUsdDifference = abbreviateNumber(
		Math.abs(usdDifference),
		locale,
		true,
	);

	return (
		<div className="bn-my-2 bn-bg-accent-1 bn-rounded-lg bn-px-4 bn-py-2 bn-flex bn-items-center bn-justify-between bn-gap-3">
			<div className="bn-flex bn-items-center bn-gap-1.5 bn-flex-1">
				<div className="bn-bg-accent-1-text bn-size-6 bn-rounded-lg bn-flex-shrink-0 bn-flex bn-items-center bn-justify-center">
					{scenario === "manual-selected-auto-better-return" ||
					scenario === "auto-selected-manual-better-return" ? (
						<Stars fill="black" />
					) : (
						<MIcon
							name="conversion_path"
							classNames="bn-text-black bn-text-sm"
						/>
					)}
				</div>

				{/* Message Text */}
				<span className="bn-text-primary bn-text-sm bn-font-medium bn-aeonik-font">
					{scenario === "switched-to-manual" &&
						"Only Manual routes are available"}
					{scenario === "switched-to-auto" && "Only Auto routes are available"}
					{scenario === "manual-selected-auto-better-return" &&
						`+$${formattedUsdDifference} available with Auto`}
					{scenario === "auto-selected-manual-better-return" &&
						`+$${formattedUsdDifference} available with Manual`}
					{scenario === "auto-no-routes-suggest-manual" &&
						"No Auto routes available"}
					{scenario === "manual-no-routes-suggest-auto" &&
						"No Manual routes available"}
				</span>
			</div>

			{(scenario === "manual-selected-auto-better-return" ||
				scenario === "auto-selected-manual-better-return" ||
				scenario === "auto-no-routes-suggest-manual" ||
				scenario === "manual-no-routes-suggest-auto") && (
				<button
					type="button"
					onClick={
						scenario === "manual-selected-auto-better-return" ||
						scenario === "manual-no-routes-suggest-auto"
							? handleTryAuto
							: handleTryManual
					}
					className="bn-flex bn-items-center bn-gap-1 bn-text-accent-1 bn-text-sm bn-font-medium bn-cursor-pointer hover:bn-opacity-80 bn-transition-opacity bn-flex-shrink-0"
				>
					<span>Switch</span>
					<MIcon
						name="arrow_forward"
						classNames="bn-text-base bn-text-accent-1"
					/>
				</button>
			)}
		</div>
	);
};
