import type { ReduxStateType } from "@store/types";
import { useCallback, useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";

import type { InflightInfo } from "@components/InFlight/common/data";
import { getSubtitle, getTitle } from "@components/InFlight/common/utils";
import { Button } from "@components/common/Button";
import { ModalCloseBtn } from "@components/common/ModalHeader";
import type { AutoOrderData } from "@hooks/apis/auto/useAutoHistory";
import type {
	FormattedAutoQuote,
	FormattedManualQuote,
} from "@hooks/apis/common/quote/types";
import { useTopRoutes } from "@hooks/apis/common/quote/useTopRoutes";
import { isAutoQuote, isManualQuote } from "@hooks/apis/common/quote/utils";
import { useConfig } from "@hooks/useConfig";
import { useMappedChainData } from "@hooks/useMappedChainData";
import { useTransferLog } from "@hooks/useTransferLog";
import { ScreenTab, setScreenTab } from "@store/globalSlice";
import {
	addOutputToken,
	setAmount,
	setFromChainId,
	setFromTokens,
	setIsFetchingDisabled,
	setToChainId,
} from "@store/quoteParamSlice";
import { setSlippage } from "@store/settingsSlice";
import { NATIVE_TOKEN_ADDRESS } from "@utils/constants";
import { getOrderStatus } from "@utils/getOrderStatus";
import { FAQ } from "./FAQ";
import { InflightBanner } from "./InFlightBanner";
import { InfoSection } from "./InfoSection";
import { RotatingText } from "./RotatingText";

export const InFlightLayout = ({ data }: { data: InflightInfo }) => {
	const dispatch = useDispatch();
	const [isFaqOpen, toggleFaq] = useState<boolean>(false);
	const paramAmount = useSelector(
		(state: ReduxStateType) => state.quoteParams.amounts,
	);
	const mappedChainData = useMappedChainData();

	const { refetch } = useTopRoutes();
	const bungeeConfig = useConfig();

	const {
		swapTime,
		statusCode,
		input,
		output,
		primaryInput,
		primaryOutput,
		srcTimestamp,
		requestHash,
		routingMode,
		refund,
		// fix this
		// rebateDetails,
		includesCollectible,
	} = data.info;

	const { isCompleted, isExpired, isRefunded } = getOrderStatus(statusCode);

	const { data: refundLog, isLoading: isLoadingRefundLog } = useTransferLog({
		hash: refund?.txHash as string,
		chainId: refund?.chainId as number,
		enabled: Boolean(refund?.txHash && isRefunded),
	});

	/** timestamp could be either swap time in seconds or unix timestamp */
	const [timestamp, setTimestamp] = useState<number>(
		Math.floor(Date.now() / 1000),
	);

	// biome-ignore lint/correctness/useExhaustiveDependencies: tracking data.info instead of individual variables
	useEffect(() => {
		if (routingMode === "auto") {
			if (isCompleted) setTimestamp(swapTime);
			else setTimestamp(srcTimestamp);
		} else {
			setTimestamp(
				data.info.estimatedFulfilTime,
			); /** this needs to be replaced with swap time  */
		}
	}, [data.info, isCompleted]);

	const inputChainName =
		mappedChainData?.[primaryInput.token.chainId]?.name ?? "";
	const outputChainName =
		mappedChainData?.[primaryOutput.token.chainId]?.name ?? "";

	const useSuggestedClientSlippage =
		(data.info as AutoOrderData).suggestedClientSlippage !== data.info.slippage;

	// resetting slippage
	// setting quote params based on current route
	const retry = useCallback(() => {
		if (useSuggestedClientSlippage) {
			dispatch(setSlippage("dynamic"));
		}
		//   Explicitly pass the refunded stablecoin info (USDC, USDT, etc) as fromToken if "isRefunded" is true
		const fromChainId = isRefunded
			? refundLog?.chainId
			: primaryInput.token.chainId;
		const fromToken = isRefunded ? refundLog?.tokenInfo : primaryInput.token;
		const fromAmount = isRefunded
			? refundLog?.value?.toString()
			: primaryInput.amount;

		dispatch(setFromChainId(fromChainId || primaryInput.token.chainId));
		dispatch(setToChainId(primaryOutput.token.chainId));
		dispatch(setFromTokens(fromToken || primaryInput.token));
		dispatch(addOutputToken({ id: 0, token: primaryOutput.token }));
		dispatch(setAmount(fromAmount || primaryInput.amount));
		dispatch(setScreenTab(ScreenTab.HOME));

		if (useSuggestedClientSlippage) {
			const slippage = (data.info as AutoOrderData).suggestedClientSlippage;
			const message = slippage
				? `${slippage}% Suggested Slippage has been applied`
				: "Suggested Slippage has been applied";
			bungeeConfig?.eventHandlers?.onEvent?.("success", {
				title: "",
				message,
				action: "TRANSACTION",
			});
		}
	}, [
		bungeeConfig,
		data.info,
		isRefunded,
		refundLog,
		useSuggestedClientSlippage,
		primaryInput,
		primaryOutput,
		dispatch,
	]);

	const isGasless =
		routingMode === "auto" &&
		primaryInput.token.address.toLowerCase() !==
			NATIVE_TOKEN_ADDRESS.toLowerCase();

	/* Make this more dynamic to the integrator's request */
	const showPostActionCTA =
		bungeeConfig?.postSwapAction?.ctaLabel &&
		includesCollectible !== false &&
		isCompleted &&
		(isAutoQuote(data.info as unknown as FormattedAutoQuote) ||
			(isManualQuote(data.info as unknown as FormattedManualQuote) &&
				primaryInput.token.chainId !== primaryOutput.token.chainId));

	return (
		<>
			<div className="bn-relative">
				<InflightBanner
					statusCode={statusCode}
					input={input}
					output={output}
					timeStamp={timestamp}
					protocol={
						data.info.routingMode === "manual" ? data.info.protocol : undefined
					}
					refuel={data.info.routingMode === "manual" ? data.info.refuel : null}
				/>

				<div className="bn-flex bn-flex-col bn-justify-center bn-w-full bn-my-4">
					<h2
						className={`bn-text-center bn-text-xl bn-font-medium bn-leading-6 bn-mb-1 ${isCompleted ? "bn-text-accent-3" : "bn-text-primary"}`}
					>
						{getTitle(
							statusCode,
							data,
							routingMode === "manual" ? data.info.protocol.name : undefined,
							isGasless,
						)}
					</h2>
					<RotatingText
						texts={getSubtitle(
							statusCode,
							data,
							primaryInput,
							primaryOutput,
							inputChainName,
							outputChainName,
						)}
					/>
				</div>

				<InfoSection routeData={data.info} openFaq={() => toggleFaq(true)} />

				<ModalCloseBtn
					classNames="bn-absolute bn-right-3 bn-top-2 bn-bg-layer-1 bn-rounded-full"
					closeModal={() => {
						if (paramAmount?.[0] && refetch) refetch();
						dispatch(setIsFetchingDisabled(false));
						dispatch(setScreenTab(ScreenTab.HOME));
					}}
				/>
			</div>

			{(isExpired || isRefunded) && (
				<Button
					label={
						useSuggestedClientSlippage
							? "Retry with suggested slippage"
							: "Retry Swap"
					}
					classNames="bn-mt-2"
					onClick={retry}
					isLoading={isRefunded && isLoadingRefundLog}
					disabled={isRefunded && isLoadingRefundLog}
				/>
			)}

			{showPostActionCTA && (
				<Button
					label={bungeeConfig?.postSwapAction?.ctaLabel}
					classNames="bn-mt-2"
					onClick={() => bungeeConfig.postSwapAction?.ctaAction?.(requestHash)}
					isLoading={bungeeConfig?.postSwapAction?.isPending}
					disabled={bungeeConfig?.postSwapAction?.isPending}
				/>
			)}

			<FAQ isVisible={isFaqOpen} closePanel={() => toggleFaq(!isFaqOpen)} />
		</>
	);
};
