import { useCallback, useEffect, useRef, useState } from 'react';

import {
  type ApprovalRequest,
  type CategorizedHourApprovalStep,
} from 'src/types/timeTracking';

type UseSupersededApprovalStepAlertParams = {
  categorizedHourId: string | null;
  categorizedHour?: ApprovalRequest;
  isLoading: boolean;
  actionableStep?: CategorizedHourApprovalStep;
  lastReviewedStep?: CategorizedHourApprovalStep;
  isCurrentUserInApprovers?: boolean;
  canManageTimeTracking: boolean;
  isReviewMutationLoading: boolean;
};

export const useSupersededApprovalStepAlert = ({
  categorizedHourId,
  categorizedHour,
  isLoading,
  actionableStep,
  lastReviewedStep,
  isCurrentUserInApprovers = false,
  canManageTimeTracking,
  isReviewMutationLoading,
}: UseSupersededApprovalStepAlertParams) => {
  /**
   * Heuristic alert: when the actionable step changes and there is no local review mutation in-flight,
   * we assume another approver advanced the flow while this drawer was open.
   *
   * Known caveats:
   * - A self-triggered refetch outside the local mutation window can look like an external action.
   * - Fast navigation between different request ids can leak previous refs if we do not reset eagerly.
   *
   * TODO: Replace this with an explicit server signal from socket payloads
   * (e.g. actorId and/or mutation correlation token) to avoid inference-based false positives.
   */
  const [showSupersededByOtherApprover, setShowSupersededByOtherApprover] =
    useState(false);
  const prevActionableStepIdRef = useRef<string | number | null>(null);
  const prevWasUserPotentialApproverRef = useRef(false);
  const prevCategorizedHourIdRef = useRef<string | null>(null);

  const categorizedHourEntityId = categorizedHour?.id;
  const actionableStepId = actionableStep?.id ?? null;

  useEffect(() => {
    if (prevCategorizedHourIdRef.current !== categorizedHourId) {
      prevCategorizedHourIdRef.current = categorizedHourId;
      prevActionableStepIdRef.current = null;
      prevWasUserPotentialApproverRef.current = false;
      setShowSupersededByOtherApprover(false);
    }

    if (!categorizedHourId || categorizedHourEntityId == null || isLoading) {
      return;
    }
    if (String(categorizedHourEntityId) !== String(categorizedHourId)) {
      return;
    }

    const isUserPotentialOnActionable = !!isCurrentUserInApprovers;
    const prevId = prevActionableStepIdRef.current;
    const prevWasPotential = prevWasUserPotentialApproverRef.current;

    const actionableAdvanced =
      prevId != null &&
      (actionableStepId == null || String(prevId) !== String(actionableStepId));

    if (
      actionableAdvanced &&
      !isReviewMutationLoading &&
      (prevWasPotential || canManageTimeTracking)
    ) {
      setShowSupersededByOtherApprover(true);
    }

    prevActionableStepIdRef.current = actionableStepId;
    prevWasUserPotentialApproverRef.current = isUserPotentialOnActionable;
  }, [
    categorizedHourId,
    categorizedHourEntityId,
    isLoading,
    actionableStepId,
    isCurrentUserInApprovers,
    canManageTimeTracking,
    isReviewMutationLoading,
  ]);

  const reset = useCallback(() => {
    setShowSupersededByOtherApprover(false);
    prevActionableStepIdRef.current = null;
    prevWasUserPotentialApproverRef.current = false;
    prevCategorizedHourIdRef.current = null;
  }, []);

  return {
    showSupersededByOtherApprover,
    supersededStepPosition: showSupersededByOtherApprover
      ? lastReviewedStep?.position
      : undefined,
    reset,
  };
};
