import { useCallback, useRef, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
  Box,
  Button,
  Group,
  Image,
  Loader,
  Modal,
  Paper,
  Stack,
  Text,
  TextInput,
} from "@mantine/core";
import { ArrowLeft, Download, FileSignature, Printer } from "lucide-react";
import toast from "react-hot-toast";

import { ContractSignSuccessModal } from "@/components/contracts/ContractSignSuccessModal";
import { ContractSignaturePad } from "@/components/bookings/ContractSignaturePad";
import { StampUpload } from "@/components/contracts/StampUpload";
import { contractsService } from "@/services/contracts.service";
import { extractApiError } from "@/utils/result";
import { QUERY_KEYS } from "@/constants/QUERY_KEYS";
import { useAuth } from "@/auth/useAuth";
import { FREIGHT_PERMS, hasPermission } from "@/lib/permissions";

/**
 * Staff contract preview + sign. Staff must open and read the generated
 * contract here before signing.
 */
export default function ContractViewPage() {
  const { id } = useParams<{ id: string }>();
  const navigate = useNavigate();
  const qc = useQueryClient();
  const iframeRef = useRef<HTMLIFrameElement>(null);
  const { user } = useAuth();

  const [signOpen, setSignOpen] = useState(false);
  const [successOpen, setSuccessOpen] = useState(false);
  const [signerName, setSignerName] = useState("");
  const [signatureData, setSignatureData] = useState<string | null>(null);
  const [stampData, setStampData] = useState<string | null>(null);
  const [drawNew, setDrawNew] = useState(false);

  const { data, isLoading, isError, refetch } = useQuery({
    queryKey: [...QUERY_KEYS.CONTRACTS.byId(id ?? ""), "contract-view"],
    queryFn: () => contractsService.getContractView(id!),
    enabled: Boolean(id),
  });

  const savedSignatureImage = data?.savedSignature?.signatureImageUrl ?? null;
  const usingSaved = Boolean(savedSignatureImage) && !drawNew;

  const signMutation = useMutation({
    mutationFn: () =>
      contractsService.signContract(id!, {
        role: "STAFF",
        signatureImageBase64: usingSaved
          ? (savedSignatureImage as string)
          : (signatureData ?? ""),
        stampImageBase64: stampData ?? "",
        signerDisplayName: signerName.trim(),
        consentText: "I confirm this contract on behalf of EDR.",
      }),
    onSuccess: () => {
      setSignOpen(false);
      setSuccessOpen(true);
      void refetch();
      void qc.invalidateQueries({ queryKey: QUERY_KEYS.CONTRACTS.byId(id!) });
      void qc.invalidateQueries({ queryKey: QUERY_KEYS.CONTRACTS.ROOT });
    },
    // Surface the server's reason verbatim — the missing-customer-stamp gate
    // and the status guards all explain themselves in the message.
    onError: (err) =>
      toast.error(
        extractApiError(err).message ?? "Failed to sign contract",
      ),
  });

  const handlePrint = () => iframeRef.current?.contentWindow?.print();

  const downloadPdf = useCallback(async () => {
    if (!id) return;
    try {
      const blob = await contractsService.downloadContractDocument(id);
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a");
      a.href = url;
      a.download = `contract-${data?.reference ?? id}.pdf`;
      a.click();
      URL.revokeObjectURL(url);
    } catch {
      toast.error("Could not download contract PDF.");
    }
  }, [id, data?.reference]);

  const openSign = () => {
    setSignerName(data?.savedSignature?.signerDisplayName ?? "");
    setSignatureData(null);
    setStampData(null);
    setDrawNew(false);
    setSignOpen(true);
  };

  const confirmSign = () => {
    if (!signerName.trim() || !stampData) return;
    const image = usingSaved ? savedSignatureImage : signatureData;
    if (!image) return;
    signMutation.mutate();
  };

  if (isLoading) {
    return (
      <Group justify="center" mih="40vh" align="center">
        <Loader color="edr-green" />
      </Group>
    );
  }

  if (isError || !data) {
    return (
      <Box p="xl">
        <Text c="dimmed">Could not load contract.</Text>
        <Button variant="default" mt="md" onClick={() => navigate(-1)}>
          Go back
        </Button>
      </Box>
    );
  }

  // Counter-signature permission is split per freight type — a bulk signer must
  // not sign a container contract (API enforces the same on POST /contract/sign).
  const maySign = hasPermission(
    user,
    FREIGHT_PERMS.contracts.signStaff[
      data.freightType === "BULK" ? "bulk" : "container"
    ],
  );

  return (
    <Box p={{ base: "md", md: "xl" }}>
      <Box maw={920} mx="auto">
        <Group justify="space-between" wrap="wrap" gap="sm" mb="md">
          <Button
            variant="subtle"
            color="gray"
            leftSection={<ArrowLeft size={16} />}
            onClick={() =>
              navigate(`/dashboard/contract-requests/${data.contractId}`)
            }
          >
            Back to contract
          </Button>
          <Group gap="sm">
            <Button
              variant="default"
              leftSection={<Printer size={16} />}
              onClick={handlePrint}
            >
              Print
            </Button>
            <Button
              variant="default"
              leftSection={<Download size={16} />}
              onClick={() => void downloadPdf()}
            >
              Download PDF
            </Button>
            {data.canSignStaff && maySign && (
              <Button
                color="edr-green"
                leftSection={<FileSignature size={16} />}
                onClick={openSign}
              >
                {usingSaved ? "Approve & sign" : "Sign as staff"}
              </Button>
            )}
          </Group>
        </Group>

        <Paper withBorder radius="lg" p={0} style={{ overflow: "hidden" }}>
          <iframe
            ref={iframeRef}
            srcDoc={data.html}
            title="Contract document"
            style={{
              width: "100%",
              minHeight: "80vh",
              border: "none",
              background: "white",
            }}
          />
        </Paper>
      </Box>

      <Modal
        opened={signOpen}
        onClose={() => setSignOpen(false)}
        title="Sign contract as staff"
        centered
        radius="lg"
      >
        <Stack gap="md">
          <Text size="sm" c="dimmed">
            {data.reference} — your signature is stored securely on the
            contract.
          </Text>
          <TextInput
            label="Full name"
            value={signerName}
            onChange={(e) => setSignerName(e.currentTarget.value)}
          />
          {usingSaved ? (
            <Stack gap="xs">
              <Paper
                withBorder
                radius="md"
                p="xs"
                style={{ borderStyle: "dashed" }}
              >
                <Image
                  src={savedSignatureImage ?? undefined}
                  alt="Saved signature"
                  fit="contain"
                  h={140}
                />
              </Paper>
              <Button
                variant="subtle"
                size="compact-xs"
                color="edr-green"
                onClick={() => {
                  setDrawNew(true);
                  setSignatureData(null);
                }}
              >
                Draw a new signature instead
              </Button>
            </Stack>
          ) : (
            <ContractSignaturePad onChange={setSignatureData} />
          )}

          <StampUpload
            value={stampData}
            onChange={setStampData}
            label="EDR company stamp"
            description="Attach the official EDR stamp or seal — it is applied to the contract next to the signature."
          />

          <Group justify="flex-end" gap="sm">
            <Button variant="default" onClick={() => setSignOpen(false)}>
              Cancel
            </Button>
            <Button
              color="edr-green"
              loading={signMutation.isPending}
              disabled={
                signMutation.isPending ||
                !signerName.trim() ||
                (!usingSaved && !signatureData) ||
                !stampData
              }
              onClick={confirmSign}
            >
              {usingSaved ? "Approve & sign" : "Confirm signature"}
            </Button>
          </Group>
        </Stack>
      </Modal>

      <ContractSignSuccessModal
        opened={successOpen}
        reference={data.reference}
        message="The contract has been counter-signed. The customer will be notified of the next steps."
        onClose={() => {
          setSuccessOpen(false);
          navigate(`/dashboard/contract-requests/${data.contractId}`);
        }}
      />
    </Box>
  );
}
