import { useCallback, useEffect, useRef } from "react";
import { useDispatch, useSelector } from "react-redux";

import { RequestStatusEnum } from "@/types/index";
import type { ManualOrderData } from "@hooks/apis/auto/useAutoHistory";
import { useAccounts } from "@hooks/useAccounts";
import { useConfig } from "@hooks/useConfig";
import { updateManualHistory } from "@store/globalSlice";
import type { ReduxStateType } from "@store/types";
import { bungeeApiFetcher } from "@utils/fetcher";

export const usePendingTransactionStatusChecker = () => {
	const dispatch = useDispatch();
	const { accounts } = useAccounts();
	const { apiKey, baseUrl, affiliateId } = useConfig();
	const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);

	const manualHistory = useSelector(
		(state: ReduxStateType) => state.global.manualHistory,
	);

	// Get all pending transactions across all user addresses
	const pendingTransactions = useRef<ManualOrderData[]>([]);

	const checkTransactionStatus = useCallback(
		async (transaction: ManualOrderData) => {
			// Skip if requestHash is undefined or null
			if (!transaction.requestHash) {
				console.warn("Skipping status check: requestHash is undefined or null");
				return;
			}

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

				const response = await bungeeApiFetcher({
					query,
					apiKey,
					affiliateId,
				});

				const statusData = response?.result?.[0];

				if (!statusData) return;

				// Update transaction based on status
				let updatedTransaction: ManualOrderData = { ...transaction };
				let shouldUpdate = false;

				// Check if status has changed
				if (
					statusData.destinationData?.status === "COMPLETED" &&
					transaction.statusCode !== RequestStatusEnum.COMPLETED
				) {
					updatedTransaction = {
						...transaction,
						status: "COMPLETED",
						statusCode: RequestStatusEnum.COMPLETED,
						output: statusData.destinationData.output
							? [
									{
										...transaction.primaryOutput,
										fulfilledAmount:
											statusData.destinationData.output[0]?.fulfilledAmount,
									},
								]
							: transaction.output,
						primaryOutput: statusData.destinationData.output
							? {
									...transaction.primaryOutput,
									fulfilledAmount:
										statusData.destinationData.output[0]?.fulfilledAmount,
								}
							: transaction.primaryOutput,
					};
					shouldUpdate = true;
				}

				// Update Redux store if status changed
				if (shouldUpdate) {
					dispatch(
						updateManualHistory({
							address: transaction.sender.toLowerCase(),
							data: updatedTransaction,
						}),
					);
				}
			} catch (error) {
				console.warn(
					`Failed to check status for transaction ${transaction.requestHash}:`,
					error,
				);
			}
		},
		[baseUrl, apiKey, affiliateId, dispatch],
	);

	const stopStatusPolling = useCallback(() => {
		if (intervalRef.current) {
			clearInterval(intervalRef.current);
			intervalRef.current = null;
		}
	}, []);

	const startStatusPolling = useCallback(() => {
		// Clear any existing interval
		stopStatusPolling();

		// Poll every 15 seconds for pending transactions
		intervalRef.current = setInterval(async () => {
			const currentPendingTxs = pendingTransactions.current;

			if (currentPendingTxs.length === 0) {
				stopStatusPolling();
				return;
			}

			// Check status for all pending transactions
			const statusChecks = currentPendingTxs.map(checkTransactionStatus);
			await Promise.allSettled(statusChecks);
		}, 15000); // 15 second interval
	}, [checkTransactionStatus, stopStatusPolling]);

	useEffect(() => {
		if (!accounts?.length || !manualHistory) {
			return;
		}

		// Collect all pending transactions from all user addresses
		const allPendingTxs: ManualOrderData[] = [];

		for (const account of accounts) {
			if (!account.address) continue;

			const userHistory = manualHistory[account.address.toLowerCase()];
			if (!userHistory?.length) continue;

			const pendingTxs = userHistory.filter(
				(tx) =>
					(tx.statusCode === RequestStatusEnum.PENDING ||
						tx.statusCode === RequestStatusEnum.EXTRACTED) &&
					tx.flowType !== "bundled", // Skip bundled transactions
			);
			allPendingTxs.push(...pendingTxs);
		}

		pendingTransactions.current = allPendingTxs;

		// Start polling if we have pending transactions
		if (allPendingTxs.length > 0) {
			startStatusPolling();
		} else {
			stopStatusPolling();
		}

		return () => stopStatusPolling();
	}, [accounts, manualHistory, startStatusPolling, stopStatusPolling]);
};
