import { useEffect, useMemo, useState } from "react";
import { useDispatch } from "react-redux";
import type {
	GetTransactionReceiptErrorType,
	SendTransactionErrorType,
} from "viem";
import { useAccount, useSendTransaction, useTransactionReceipt } from "wagmi";

import { Button } from "@components/common/Button";
import { SwitchChain } from "@components/common/SwitchChain";
import type { AutoOrderData } from "@hooks/apis/auto/useAutoHistory";
import type { FormattedAutoQuote } from "@hooks/apis/common/quote/types";
import { useConfig } from "@hooks/useConfig";
import { useToast } from "@providers/ToastProvider";
import { ScreenTab, setScreenTab } from "@store/globalSlice";
import { setInflightData } from "@store/inflightSlice";
import { NATIVE_TOKEN_ADDRESS } from "@utils/constants";
import { getCommonErrors } from "@utils/getCommonErrors";
import { isWrapUnwrapCase } from "@utils/isWrapUnwrapCase";
import type { QueryStatus } from "./SignOrder";

export const SendNativeTransaction = ({
	quoteData,
}: { quoteData: FormattedAutoQuote }) => {
	const [status, setStatus] = useState<QueryStatus>("idle");

	const { showToast } = useToast();
	const dispatch = useDispatch();
	const { chainId } = useAccount();
	const bungeeConfig = useConfig();

	const {
		txData,
		output,
		requestHash,
		requestType,
		primaryInput,
		primaryOutput,
	} = quoteData;

	const {
		sendTransaction,
		isSuccess,
		error,
		data: txHash,
	} = useSendTransaction();
	const {
		data: txResolved,
		error: txError,
		isSuccess: txSuccess,
		isPending: isTxStatusPending,
	} = useTransactionReceipt({
		hash: txHash,
		query: {
			enabled: Boolean(txHash) && !!isWrapUnwrapCase(quoteData),
		},
	});

	const isNativeToken = useMemo(
		() => primaryInput?.token?.address?.toLowerCase() === NATIVE_TOKEN_ADDRESS,
		[primaryInput],
	);

	function getButtonLabel() {
		if (txHash && isTxStatusPending) return "Waiting for confirmation";
		if (status === "awaiting_wallet_confirmation") return "Confirm in wallet";
		if (status === "loading") return "Swapping";

		if (isWrapUnwrapCase(quoteData)) {
			if (isNativeToken) return "Wrap";
			return "Unwrap";
		}

		return "Swap";
	}

	function loadingState() {
		return status === "awaiting_wallet_confirmation" || status === "loading";
	}

	const initiateTransaction = () => {
		setStatus("awaiting_wallet_confirmation");
		sendTransaction(txData || {});
	};

	/** For inbox (native) txs */
	// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
	useEffect(() => {
		if (isSuccess && dispatch && !isWrapUnwrapCase(quoteData)) {
			setStatus("idle");
			const _output = output.map((item) => ({
				...item,
				minAmountOut: quoteData.minOutput?.amount ?? "",
			}));
			// to pre populate the inflight screen
			const _initialData: AutoOrderData = {
				...quoteData,
				status: "PENDING",
				statusCode: 0,
				srcTimestamp: 0, // just a placeholder
				orderTimestamp: 0, // placeholder
				swapTime: 0, // placeholder
				output: _output,
				primaryOutput: _output[0],
			};

			if (requestHash && requestType) {
				dispatch(
					setInflightData({
						data: _initialData,
					}),
				);
				dispatch(setScreenTab(ScreenTab.INFLIGHT));
			}
		}
	}, [isSuccess, dispatch]);

	/** For wrap/unwrap transactions */
	// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
	useEffect(() => {
		if (isWrapUnwrapCase(quoteData) && (txResolved || txSuccess)) {
			setStatus("idle");
			const destTokenSymbol = primaryOutput?.token?.symbol;
			const srcTokenSymbol = primaryInput?.token?.symbol;

			const _label = isNativeToken ? "Wrapping Successful" : "Unwrapping Successful";
			// biome-ignore format:
			const _subtext = isNativeToken ? `Wrapped ${srcTokenSymbol} to ${destTokenSymbol}` : `Unwrapped ${srcTokenSymbol} to ${destTokenSymbol}`

			showToast(_label, _subtext);
			bungeeConfig?.eventHandlers?.onEvent?.("success", {
				title: _label,
				message: _subtext,
				action: "TRANSACTION",
			});

			dispatch(setScreenTab(ScreenTab.HOME));
		}
	}, [txResolved, dispatch]);

	// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
	useEffect(() => {
		const handleError = (
			err: SendTransactionErrorType | GetTransactionReceiptErrorType,
		) => {
			console.log("Error: ", err);
			setStatus("error");
			const { name, shortMessage } = getCommonErrors(err);
			showToast(name, shortMessage, "error");

			bungeeConfig?.eventHandlers?.onEvent?.("error", {
				title: name,
				message: shortMessage,
				action: "TRANSACTION",
			});
		};

		if (error?.name) {
			handleError(error as SendTransactionErrorType);
		}

		if (txError?.name) {
			handleError(txError);
		}
	}, [error, txError]);

	if (chainId !== primaryInput.token.chainId) {
		return <SwitchChain switchTo={primaryInput.token.chainId} />;
	}

	return (
		<Button
			label={getButtonLabel()}
			disabled={loadingState()}
			isLoading={loadingState()}
			onClick={initiateTransaction}
		/>
	);
};
