import { useQuery } from "@tanstack/react-query";

import type { Input, Output, RouteDetails, STATUS_CODE } from "@/types/index";
import { RequestStatusEnum } from "@/types/index";
import { useConfig } from "@hooks/useConfig";
import { useLogError } from "@hooks/useLogError";
import { bungeeApiFetcher } from "@utils/fetcher";
import { useCallback, useEffect, useRef } from "react";
import type { Refund } from "../auto/useAutoHistory";

export const useStatus = ({
	requestHash,
	enabled = true,
}: {
	requestHash: string;
	enabled?: boolean;
}) => {
	const { apiKey, baseUrl, affiliateId } = useConfig();
	const { logError } = useLogError();
	const shouldFetch = Boolean(requestHash);
	const shouldStopPolling = useRef(false);

	const query = `${baseUrl}/bungee/status?requestHash=${requestHash}`;

	// Function to check if the status is final (should stop polling)
	const isFinalStatus = useCallback((statusCode?: STATUS_CODE) => {
		if (!statusCode) return false;
		return [
			RequestStatusEnum.COMPLETED,
			RequestStatusEnum.SETTLED,
			RequestStatusEnum.EXPIRED,
			RequestStatusEnum.CANCELLED,
			RequestStatusEnum.REFUNDED,
			RequestStatusEnum.REVERTED,
			RequestStatusEnum.REFUND_PENDING, // statusCode 7 means refunded in BE but status is pending in FE
		].includes(statusCode);
	}, []);

	const { data, isLoading, refetch, error } = useQuery({
		queryKey: ["bungee-auto-status", apiKey, requestHash],
		queryFn: async () => {
			const _data = await bungeeApiFetcher({
				query,
				apiKey,
				affiliateId,
			});
			const statusData = _data?.result?.[0] as StatusItem;
			if (isFinalStatus(statusData?.bungeeStatusCode)) {
				shouldStopPolling.current = true;
			}
			// statusCode 7 means refunded in BE but status is pending in FE
			statusData.bungeeStatusCode =
				statusData?.bungeeStatusCode === RequestStatusEnum.REFUND_PENDING
					? RequestStatusEnum.REFUNDED
					: statusData?.bungeeStatusCode;
			return statusData;
		},
		enabled: Boolean(shouldFetch && enabled && !shouldStopPolling.current),
		refetchOnWindowFocus: false,
		retry: (value) => {
			if (value > 1) {
				shouldStopPolling.current = true;
				return false;
			}
			return true;
		},
		refetchInterval: shouldStopPolling.current ? false : 10000,
	});

	useEffect(() => {
		if (error && logError) {
			logError(error, {
				api: "status",
				query,
			});
		}
	}, [error, logError, query]);

	return {
		data,
		isLoading,
		refetch,
	};
};

export interface StatusItem {
	hash: string;
	bungeeStatusCode: STATUS_CODE;
	routeDetails: RouteDetails;
	originData: OriginStatusData;
	destinationData: DestinationStatusData;
	refund?: Refund | null;
}

export interface OriginStatusData {
	input: Input[];
	originChainId: number;
	txHash: string | null;
	userAddress: string;
	status: keyof typeof RequestStatusEnum;
	timestamp: number | null;
}

export interface DestinationStatusData {
	output: Output[];
	destinationChainId: number;
	txHash: string | null;
	receiverAddress: string;
	status: keyof typeof RequestStatusEnum;
	timestamp: number | null;
}
