import { useEffect, useMemo } from "react";
import { useSelector } from "react-redux";
import { useCallsStatus } from "wagmi";

import { RequestStatusEnum, type STATUS_CODE } from "@/types/index";
import type { AutoOrderData } from "@hooks/apis/auto/useAutoHistory";
import type { ReduxStateType } from "@store/types";
import {
  type TrackOrderStatus,
  onCompleteSwap,
  trackOrderStatus,
} from "../../../analytics/events";
import { trackOnceIfNotAlready } from "../../../analytics/trackOnceIfNotAlready";
import { AutoData, type InflightInfo } from "../common/data";
import { useUpdateAutoStatus } from "../common/useUpdateAutoStatus";
import { InFlightLayout } from "../layout";
import { deriveCallsStatus } from "./ManualInFlight";

export const AutoInflight = () => {
  const { data: initialData } = useSelector(
    (state: ReduxStateType) => state.inflight
  );

  const routeData = useUpdateAutoStatus({
    initialData: initialData as AutoOrderData,
  });

  const isBatchingFlow = initialData?.flowType === "bundled";

  const { data: callsData, error: callsStatusError } = useCallsStatus({
    id: initialData?.batchId as string,
    query: {
      refetchInterval: 3000,
      enabled:
        isBatchingFlow &&
        routeData?.status !== "COMPLETED" &&
        routeData?.status !== "SETTLED",
    },
  });

  const effectiveCallsStatus = deriveCallsStatus(callsData);

  // only updating the status in case of failure
  // status api (useUpdateAutoStatus) handles the success status
  const updatedRouteData = useMemo(() => {
    let status: keyof typeof RequestStatusEnum;
    let statusCode: STATUS_CODE;

    if (effectiveCallsStatus === "reverted" || callsStatusError) {
      status = "REVERTED";
      statusCode = RequestStatusEnum.REVERTED;

      return {
        ...routeData,
        status,
        statusCode,
      };
    }

    return routeData;
  }, [routeData, effectiveCallsStatus, callsStatusError]);

  const data: InflightInfo = {
    title: AutoData.title,
    subTitle: AutoData.subTitle,
    // biome-ignore lint/style/noNonNullAssertion: <explanation>
    info: (updatedRouteData as AutoOrderData) ?? initialData!,
  };

  useEffect(() => {
    if (!routeData) return;

    const isFinal =
      routeData.status === "COMPLETED" || routeData.status === "REVERTED";
    if (!isFinal) return;

    const fromToken = routeData.primaryInput.token;
    const toToken = routeData.primaryOutput.token;
    const isSameSwap = fromToken?.chainId === toToken?.chainId;
    const routingMode = `${routeData.routingMode}-${
      isSameSwap ? "same-chain" : "cross-chain"
    }`;

    const orderData: TrackOrderStatus = {
      status: routeData.status === "COMPLETED" ? "success" : "failed",
      from_token: fromToken.symbol,
      to_token: toToken.symbol,
      from_chain: fromToken.chainId,
      to_chain: toToken.chainId,
      routingMode: routingMode,
      flowType: routeData?.batchId ? "bundled" : "regular",
      // note: we don't get slippage data in history api, so this data won't be accurate
      slippage: routeData?.slippage,
      suggestedClientSlippage: Boolean(routeData?.suggestedClientSlippage),
    };

    trackOnceIfNotAlready({
      type: "auto",
      requestHash: routeData.requestHash,
      trackFn: () => {
        trackOrderStatus(orderData);

        onCompleteSwap({
          status: orderData.status,
          request_hash: routeData.requestHash,
          provider_name: "",
          actual_time_seconds: routeData.orderTimestamp,
          actual_output_amount: Number(routeData.primaryOutput.amount),
          estimated_time_seconds: +new Date(routeData.orderTimestamp) / 1000,
          estimated_output_amount: Number(routeData.primaryOutput.amount),
        });
      },
    });
  }, [routeData]);

  return <InFlightLayout data={data} />;
};
