/**
 * This hooks checks the SSE and API response and updates the data accordingly
 */
import { useEffect, useState } from "react";

import type { Output } from "@/types/index";
import type { AutoOrderData } from "@hooks/apis/auto/useAutoHistory";
import { useAutoStatusSSE } from "@hooks/apis/auto/useAutoStatusSSE";
import { useStatus } from "@hooks/apis/common/useStatus";
import { formatValue } from "@utils/formatValue";

export const useUpdateAutoStatus = ({
	initialData,
}: {
	initialData: AutoOrderData | null;
}) => {
	const [data, setData] = useState<AutoOrderData>();

	const { data: statusData } = useStatus({
		requestHash: data?.requestHash ?? "",
	});

	const sseData = useAutoStatusSSE({ requestHash: data?.requestHash ?? "" });
	const {
		status: sseStatus,
		statusCode: sseStatusCode,
		fulfilAmount: sseFulfilAmount,
		srcTimestamp: sseSrcTimestamp,
		destTimestamp: sseDestTimestamp,
	} = sseData || {};

	/**
	 * checking if status api response is ahead of sse status
	 * assuming sseStatusCode is available as there is another if check below
	 */
	const sseStatusAhead =
		statusData?.bungeeStatusCode && sseStatusCode
			? sseStatusCode >= statusData.bungeeStatusCode
			: true;

	// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
	useEffect(() => {
		if (initialData) {
			// updates with the SSE data
			// if sse status is ahead of api status, only then execute the if block
			if (sseStatusCode && sseStatusAhead) {
				const primaryOutput = initialData.primaryOutput;
				const fulfilValueInUsd =
					primaryOutput.fulfilValueInUsd ||
					computeFulfilValueInUsd(primaryOutput, sseFulfilAmount ?? "0");

				const updatedPrimaryOutput = {
					...primaryOutput,
					fulfilledAmount: sseFulfilAmount ?? primaryOutput?.fulfilledAmount,
					fulfilValueInUsd,
				};

				const srcTimestamp =
					sseSrcTimestamp ?? data?.srcTimestamp ?? initialData.srcTimestamp;
				const destTimestamp =
					sseDestTimestamp ?? data?.destTimestamp ?? initialData.destTimestamp;

				const updatedData: AutoOrderData = {
					...initialData,
					// if sseStatus is unavailable, falls back to API status
					status: sseStatus ?? data?.status ?? initialData?.status, // this is not mapped with statusCode. Need to change it
					statusCode: sseStatusCode ?? data?.statusCode ?? initialData?.statusCode,
					output: [updatedPrimaryOutput],
					primaryOutput: updatedPrimaryOutput,
					srcTimestamp,
					destTimestamp,
					swapTime: calculateSwapTime(srcTimestamp, destTimestamp),
				};

				setData(updatedData);
			} else if (statusData) {
				// updates with API data
				const srcTimestamp =
					statusData.originData.timestamp ?? initialData.srcTimestamp;
				const destTimestamp =
					statusData?.destinationData?.timestamp ?? initialData.destTimestamp;

				const updatedData: AutoOrderData = {
					...initialData,
					status: statusData?.destinationData?.status,
					statusCode: statusData.bungeeStatusCode,
					srcTimestamp,
					destTimestamp,
					swapTime: calculateSwapTime(srcTimestamp, destTimestamp),
				};

				setData(updatedData);
			} else {
				setData(initialData);
			}
		}
	}, [initialData, statusData, sseData]);

	return data;
};

const computeFulfilValueInUsd = (output: Output, fulfilAmount: string) => {
	if (output?.fulfilValueInUsd) return output.fulfilValueInUsd;

	if (fulfilAmount) {
		const formattedAmount = formatValue(
			fulfilAmount.toString(),
			output.token.decimals,
		);
		return output.priceInUsd * Number(formattedAmount);
	}

	return 0;
};

const calculateSwapTime = (srcTimestamp?: number, destTimestamp?: number) => {
	if (!srcTimestamp || !destTimestamp) return 0;

	return destTimestamp - srcTimestamp;
};
