import { useCallback, useEffect, useState } from "react";
import { useDispatch } from "react-redux";
import type { Address } from "viem";
import { useAccount, useSendTransaction } from "wagmi";

import { Button } from "@components/common/Button";
import type { ManualOrderData } from "@hooks/apis/auto/useAutoHistory";
import type { FormattedManualQuote } from "@hooks/apis/common/quote/types";
import { useBuildTransaction } from "@hooks/apis/manual/useBuildTransaction";
import { useToast } from "@providers/ToastProvider";
import {
	ScreenTab,
	setScreenTab,
	updateManualHistory,
} from "@store/globalSlice";
import { setInflightData } from "@store/inflightSlice";
import { getCommonErrors } from "@utils/getCommonErrors";
import type { QueryStatus } from "../Auto/SignOrder";

export const ManualFlow = ({ data }: { data: FormattedManualQuote }) => {
	const dispatch = useDispatch();
	const {
		data: buildData,
		isLoading: isBuildingtx,
		isError: isBuildErr,
		error: buildErr,
	} = useBuildTransaction({
		routeId: data.routeId,
	});
	const { address } = useAccount();
	const { showToast } = useToast();
	const [status, setStatus] = useState<QueryStatus>("idle");

	const {
		sendTransaction,
		error,
		isSuccess,
		isError,
		data: sendTxData,
	} = useSendTransaction();

	// do I check for native amount/ or let it fail at wallet level?
	const initiatTransaction = useCallback(() => {
		setStatus("awaiting_wallet_confirmation");
		return sendTransaction({
			data: buildData.txData as Address,
			to: buildData.txTarget as Address,
			value: BigInt(buildData.value),
		});
	}, [buildData, sendTransaction]);

	// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
	useEffect(() => {
		if (isError && error) {
			setStatus("idle");
			const { name, shortMessage } = getCommonErrors(error);
			showToast(name, shortMessage, "error");
		}
	}, [isError, error]);

	// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
	useEffect(() => {
		if (isBuildErr && buildErr) {
			const { name, shortMessage } = getCommonErrors(buildErr);
			setStatus("idle");
			showToast(name, shortMessage, "error");
		}
	}, [isBuildErr, buildErr]);

	useEffect(() => {
		if (isSuccess) setStatus("idle");
	}, [isSuccess]);

	const modifiedOutput = data.output.map((item) => ({
		...item,
		minAmountOut: data.minOutput?.amount || "", // used to show output in history and inflight
	}));

	const formattedData: ManualOrderData | null = data
		? {
				...data,
				requestHash: sendTxData as string,
				output: modifiedOutput,
				orderTimestamp: Math.floor(Date.now() / 1000), // when the order is placed
				srcTimestamp: 0, // after extraction, so add it when tx receipt returns success
				swapTime: data.estimatedFulfilTime,
				primaryOutput: modifiedOutput?.[0],
				statusCode: 0, // setting to pending
				status: "PENDING",
				isSwapRoute: data.isSwapRoute,
			}
		: null;

	// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
	useEffect(() => {
		if (sendTxData && dispatch && formattedData) {
			dispatch(setInflightData({ data: formattedData }));
			dispatch(setScreenTab(ScreenTab.INFLIGHT));

			// updating the localstorage
			dispatch(
				updateManualHistory({
					data: formattedData,
					address: address?.toLowerCase() || data.sender.toLowerCase(),
				}),
			);
		}
	}, [sendTxData, dispatch]);

	function getButtonLabel() {
		if (status === "awaiting_wallet_confirmation") return "Confirm in wallet";
		// if (status === "loading") return "Submitting request";
		if (isBuildingtx) return "Building";

		return "Swap";
	}

	const disable = isBuildingtx || status === "awaiting_wallet_confirmation";

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