import { useCallback, useState } from "react";

import {
  getBookingActions,
  getNextPendingApprovalStep,
  type BookingActionContext,
  type BookingActionDef,
} from "@/features/bookings/booking-actions.config";
import { useAuth } from "@/auth/useAuth";
import { useBookingDetail, useBookingMutations } from "@/hooks/bookings/useBookings";

/** A contract validity window must be a whole number of days, 1–365. */
function isValidValidityDays(value: string): boolean {
  const days = Number(value.trim());
  return Number.isInteger(days) && days >= 1 && days <= 365;
}

/** An adjusted price must be a non-negative number. */
function isValidAmount(value: string): boolean {
  if (!value.trim()) return false;
  const amount = Number(value.trim());
  return Number.isFinite(amount) && amount >= 0;
}

export function useBookingActionDialog(
  bookingId: string,
  context: BookingActionContext,
) {
  const [pendingAction, setPendingAction] = useState<BookingActionDef | null>(null);
  const [inputValue, setInputValue] = useState("");
  const [selectedFile, setSelectedFile] = useState<File | null>(null);
  const [dialogOpen, setDialogOpen] = useState(false);

  const needsApprovalSteps =
    pendingAction?.id === "approve" || pendingAction?.id === "rejectApproval";

  const needsApprovalContext =
    context.status === "PENDING_APPROVAL" ||
    context.status === "APPROVED_PENDING_SIGNATURE";

  const { data: detail, isLoading: detailLoading } = useBookingDetail(
    needsApprovalSteps || needsApprovalContext ? bookingId : undefined,
  );

  const mergedContext: BookingActionContext = {
    ...context,
    approvalSteps: detail?.approvalSteps ?? context.approvalSteps,
    reference: detail?.reference ?? context.reference,
  };

  const { user } = useAuth();
  const mutations = useBookingMutations(bookingId);
  const actions = getBookingActions(mergedContext, user);

  const openAction = useCallback((action: BookingActionDef) => {
    setPendingAction(action);
    setInputValue("");
    setSelectedFile(null);
    setDialogOpen(true);
  }, []);

  const closeDialog = useCallback(() => {
    setDialogOpen(false);
    setPendingAction(null);
    setInputValue("");
    setSelectedFile(null);
  }, []);

  const runAction = useCallback(() => {
    if (!pendingAction) return;

    const onSuccess = () => closeDialog();

    switch (pendingAction.id) {
      case "accept": {
        const days = Number(inputValue.trim());
        if (!Number.isInteger(days) || days < 1 || days > 365) return;
        mutations.staffAccept.mutate(days, { onSuccess });
        break;
      }
      case "requestChanges":
        mutations.requestChanges.mutate(inputValue.trim(), { onSuccess });
        break;
      case "reject":
        mutations.staffReject.mutate(inputValue.trim(), { onSuccess });
        break;
      case "operationAccept":
        mutations.reviewOperation.mutate({ decision: "ACCEPT" }, { onSuccess });
        break;
      case "operationRequestChanges":
        mutations.reviewOperation.mutate(
          { decision: "REQUEST_CHANGES", note: inputValue.trim() },
          { onSuccess },
        );
        break;
      case "operationAdjustPrice": {
        const amount = Number(inputValue.trim());
        if (!Number.isFinite(amount) || amount < 0) return;
        mutations.reviewOperation.mutate(
          { decision: "ADJUST_PRICE", amount },
          { onSuccess },
        );
        break;
      }
      case "approve": {
        const step = getNextPendingApprovalStep(mergedContext.approvalSteps);
        if (!step) return;
        mutations.approveStep.mutate(
          { stepId: step.id, requiredRole: step.requiredRole },
          { onSuccess },
        );
        break;
      }
      case "rejectApproval": {
        const step = getNextPendingApprovalStep(mergedContext.approvalSteps);
        if (!step) return;
        mutations.rejectStep.mutate(
          { stepId: step.id, reason: inputValue.trim() },
          { onSuccess },
        );
        break;
      }
      case "viewContract":
        break;
      case "startTransit":
        mutations.startTransit.mutate(undefined, { onSuccess });
        break;
      case "complete":
        mutations.complete.mutate(undefined, { onSuccess });
        break;
      case "cancel":
        mutations.cancel.mutate(inputValue.trim(), { onSuccess });
        break;
      default:
        break;
    }
  }, [
    pendingAction,
    inputValue,
    selectedFile,
    mergedContext.approvalSteps,
    mutations,
    closeDialog,
  ]);

  const confirmDisabled =
    mutations.isPending ||
    (needsApprovalSteps && detailLoading) ||
    (pendingAction?.id === "approve" &&
      !getNextPendingApprovalStep(mergedContext.approvalSteps)) ||
    (pendingAction?.input === "file" && !selectedFile) ||
    (pendingAction?.input === "reason" && !inputValue.trim()) ||
    (pendingAction?.input === "note" && !inputValue.trim()) ||
    (pendingAction?.input === "days" && !isValidValidityDays(inputValue)) ||
    (pendingAction?.input === "amount" && !isValidAmount(inputValue));

  return {
    actions,
    pendingAction,
    inputValue,
    setInputValue,
    selectedFile,
    setSelectedFile,
    dialogOpen,
    setDialogOpen: (open: boolean) => {
      if (!open) closeDialog();
      else setDialogOpen(true);
    },
    openAction,
    closeDialog,
    runAction,
    mutations,
    confirmDisabled,
    detailLoading,
    mergedContext,
  };
}
