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

import { BoosterContext } from "@components/Boosters/BoosterProvider";
import { Button } from "@components/common/Button";
import { useSubmit } from "@hooks/apis/useSubmit";
import { useToast } from "@providers/ToastProvider";
import { ScreenTab, setScreenTab } from "@store/globalSlice";
import { setInflightData } from "@store/inflightSlice";
import type { ReduxStateType } from "@store/types";
import { getCommonErrors } from "@utils/getCommonErrors";
import type { FormattedQuoteData } from "@utils/getQuoteData";
import { useActionStatusContext } from "./ActionStatusProvider";

export type QueryStatus =
	| "awaiting_wallet_confirmation"
	| "loading"
	| "disabled"
	| "idle"
	| "error";

export const SignOrder = ({
	quoteData,
	disabled,
}: { quoteData: FormattedQuoteData; disabled: boolean }) => {
	const dispatch = useDispatch();
	const { showToast } = useToast();
	const [signature, setSignature] = useState<string>("");
	const [status, setStatus] = useState<QueryStatus>("idle");

	const customReceiver = useSelector(
		(state: ReduxStateType) => state.quoteParams.receiver,
	);
	const { signTypedData } = useSignTypedData();
	const boosterContext = useContext(BoosterContext);

	const { signTypedData: permit2Data, requestType } = quoteData || {};

	async function generateSignature() {
		// const timeNow = Date.now();
		// const FIFTEEN_MINUTES = 15 * 60;
		// const TWENTY_MINUTES = 20 * 60; // in seconds

		// adding deadline
		// if (boosterContext.boosters?.batching) {
		// 	const _deadline = Math.floor(timeNow / 1000) + TWENTY_MINUTES;
		// 	permit2Data.values.witness.basicReq.deadline = _deadline;
		// 	permit2Data.values.deadline = _deadline;
		// } else {
		// 	const _deadline = Math.floor(timeNow / 1000) + FIFTEEN_MINUTES;
		// 	permit2Data.values.witness.basicReq.deadline = _deadline;
		// 	permit2Data.values.deadline = _deadline;
		// }

		// updating receiver address
		// if (customReceiver) {
		// 	permit2Data.values.witness.basicReq.receiver = customReceiver;
		// } else {
		// 	permit2Data.values.witness.basicReq.receiver = receiver;
		// }

		// adding min outputs
		// if (output) {
		// 	if (requestType === "SWAP_REQUEST") {
		// 		permit2Data.values.witness.basicReq.minOutputAmounts = output.map(
		// 			(item) => item.slippageAdjustedAmount ?? item.amount,
		// 		);
		// 	} else if (requestType === "SINGLE_OUTPUT_REQUEST") {
		// 		permit2Data.values.witness.basicReq.minOutputAmount =
		// 			output?.[0]?.slippageAdjustedAmount ?? output?.[0]?.amount;
		// 	}
		// }

		setStatus("awaiting_wallet_confirmation");
		await signTypedData(
			{
				types: permit2Data.types,
				primaryType: "PermitWitnessTransferFrom",
				message: permit2Data.values,
				domain: permit2Data.domain,
			},
			{
				onSuccess: (data) => {
					setSignature(data);
				},
				onError: (data) => {
					setStatus("error");
					console.log("Error", data.message);
					const { shortMessage } = getCommonErrors(data);
					showToast("Signature Submission Failed", shortMessage, "error");
				},
			},
		);
	}

	const { data, isLoading, isError } = useSubmit({
		signature,
		requestData: JSON.stringify({
			requestType: requestType,
			request: permit2Data?.values?.witness,
			userSignature: signature,
		}),
	});

	useEffect(() => {
		if (isLoading) setStatus("loading");
		if (isError) setStatus("error");
	}, [isLoading, isError]);

	useEffect(() => {
		if (data) {
			// to pre populate the inflight screen
			const _initialData = {
				input: data.inputTokens,
				output: data.outputTokens,
				requestHash: data.requestHash,
				statusId: data.statusCode,
				userSignature: data.userSignature,
			};

			dispatch(
				setInflightData({
					requestHash: data.requestHash,
					data: _initialData,
					requestType: requestType,
				}),
			);
			dispatch(setScreenTab(ScreenTab.INFLIGHT));
		} else {
			setStatus("error");
		}
	}, [data, dispatch, requestType]);

	function getButtonLabel() {
		if (status === "awaiting_wallet_confirmation") return "Confirm in wallet";

		if (status === "loading") return "Submitting request";

		return "Swap";
	}

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

	const { setStatus: setActionStatus } = useActionStatusContext();
	useEffect(() => {
		setActionStatus(status);
	}, [status, setActionStatus]);

	return (
		<Button
			label={getButtonLabel()}
			onClick={generateSignature}
			disabled={disabled || !permit2Data || loadingState()}
			isLoading={loadingState()}
		/>
	);
};
