import { useCallback, useRef, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
  ArrowLeft,
  Download,
  FileSignature,
  Loader2,
  Printer,
} from "lucide-react";
import toast from "react-hot-toast";

import Breadcrumbs from "@/components/ui/Breadcrumbs";
import { ContractSignaturePad } from "@/components/bookings/ContractSignaturePad";
import { bookingSurface } from "@/components/bookings/booking-ui.styles";
import { QUERY_KEYS } from "@/constants/QUERY_KEYS";
import { invalidateBookingDetail } from "@/utils/queryInvalidation";
import {
  bookingsService,
  type SignContractPayload,
} from "@/services/bookings.service";
import { cn } from "@/lib/utils";
import {
  Button,
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  Input,
  Label,
} from "@edr/ui-common";

export default function BookingContractPage() {
  const { id } = useParams<{ id: string }>();
  const navigate = useNavigate();
  const qc = useQueryClient();
  const iframeRef = useRef<HTMLIFrameElement>(null);
  const [signOpen, setSignOpen] = useState(false);
  const [signerName, setSignerName] = useState("");
  const [signatureData, setSignatureData] = useState<string | null>(null);
  // When the user has a saved signature we offer it for approval first; they
  // can switch to drawing a fresh one.
  const [drawNew, setDrawNew] = useState(false);

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

  // Backoffice only ever signs as STAFF — customers sign in the portal.
  const canSign = Boolean(data?.canSignStaff);

  const savedSignature = data?.savedSignature ?? null;
  const savedSignatureImage = savedSignature?.signatureImageUrl ?? null;
  // Show the approval view only while a saved signature exists and the user
  // hasn't opted to draw a new one.
  const usingSaved = Boolean(savedSignatureImage) && !drawNew;

  const signMutation = useMutation({
    mutationFn: (payload: SignContractPayload) =>
      bookingsService.signContract(id!, payload),
    onSuccess: async () => {
      toast.success("Signature recorded");
      setSignOpen(false);
      await invalidateBookingDetail(qc, id!);
      qc.invalidateQueries({
        queryKey: [...QUERY_KEYS.BOOKINGS.byId(id ?? ""), "contract-view"],
      });
    },
    onError: () => toast.error("Failed to sign contract"),
  });

  const downloadPdf = useCallback(async () => {
    if (!id) return;
    try {
      const blob = await bookingsService.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("Contract PDF not available. Ask staff to generate it first.");
    }
  }, [id, data?.reference]);

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

  const openSign = () => {
    // Prefill from the saved signature when available so the user only has to
    // approve it; otherwise start with an empty pad.
    setSignerName(savedSignature?.signerDisplayName ?? "");
    setSignatureData(null);
    setDrawNew(false);
    setSignOpen(true);
  };

  const confirmSign = () => {
    if (!canSign || !signerName.trim()) return;
    // Approve the saved signature, or submit the freshly drawn one.
    const image = usingSaved ? savedSignatureImage : signatureData;
    if (!image) return;
    signMutation.mutate({
      role: "STAFF",
      signatureImageBase64: image,
      signerDisplayName: signerName.trim(),
      consentText: "I agree to the terms of this contract.",
    });
  };

  if (isLoading) {
    return (
      <div className="flex min-h-[40vh] items-center justify-center">
        <Loader2 className="size-8 animate-spin text-primary" />
      </div>
    );
  }

  if (isError || !data) {
    return (
      <div className={bookingSurface.pageInner}>
        <p className="text-muted-foreground">Could not load contract.</p>
        <Button variant="outline" className="mt-4" onClick={() => navigate(-1)}>
          Go back
        </Button>
      </div>
    );
  }

  return (
    <div className={bookingSurface.page}>
      <div className={cn(bookingSurface.pageInner, "print:p-0")}>
        <div className="print:hidden">
          <Breadcrumbs
            items={[
              { label: "Booking requests", href: "/dashboard/booking-requests" },
              {
                label: data.reference,
                href: `/dashboard/booking-requests/${id}`,
              },
              { label: "Contract" },
            ]}
          />
        </div>

        <div style={{boxShadow:"3px 3px 20px 1px lightgrey"}} className="sticky top-0 z-10 mb-6 flex flex-wrap items-center justify-between gap-3 rounded-xl border bg-background/95 p-4 shadow-sm backdrop-blur print:hidden">
          <Button variant="ghost" size="sm" className="gap-2" onClick={() => navigate(-1)}>
            <ArrowLeft className="size-4" />
            Back
          </Button>
          <div className="flex flex-wrap gap-2">
            <Button variant="outline" size="sm" className="gap-2" onClick={handlePrint}>
              <Printer className="size-4" />
              Print
            </Button>
            <Button variant="outline" size="sm" className="gap-2" onClick={downloadPdf}>
              <Download className="size-4" />
              Download PDF
            </Button>
            {canSign && (
              <Button size="sm" className="gap-2" onClick={openSign}>
                <FileSignature className="size-4" />
                {usingSaved ? "Approve & sign" : "Sign contract"}
              </Button>
            )}
          </div>
        </div>

        {!data.hasContractDocument && (
          <div className="mb-4 rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-900 print:hidden">
            A PDF has not been stored yet. Download will generate the latest
            contract document automatically.
          </div>
        )}

        <iframe
          ref={iframeRef}
          title={`Contract ${data.reference}`}
          srcDoc={data.html}
          sandbox="allow-same-origin"
          className="mx-auto block min-h-[297mm] w-full max-w-[210mm] rounded-xl border bg-white shadow-sm print:h-[297mm] print:border-0 print:shadow-none"
        />

        <Dialog open={signOpen} onOpenChange={setSignOpen}>
          <DialogContent className="sm:max-w-md">
            <DialogHeader>
              <DialogTitle>Staff signature</DialogTitle>
              <DialogDescription>
                {usingSaved
                  ? `Review your saved signature and approve it to execute the contract for ${data.reference}.`
                  : `Sign to execute the contract for ${data.reference}.`}
              </DialogDescription>
            </DialogHeader>
            <div className="space-y-4">
              <div className="space-y-2">
                <Label htmlFor="signerName">Full name</Label>
                <Input
                  id="signerName"
                  value={signerName}
                  onChange={(e) => setSignerName(e.target.value)}
                  placeholder="As shown on the contract"
                />
              </div>
              {usingSaved ? (
                <div className="space-y-2">
                  <Label>Saved signature</Label>
                  <div className="overflow-hidden rounded-lg border-2 border-dashed border-border bg-white">
                    <img
                      src={savedSignatureImage ?? undefined}
                      alt="Saved signature"
                      className="mx-auto h-36 w-full object-contain"
                    />
                  </div>
                  <Button
                    type="button"
                    variant="link"
                    size="sm"
                    className="h-auto p-0 text-xs"
                    onClick={() => {
                      setDrawNew(true);
                      setSignatureData(null);
                    }}
                  >
                    Draw a new signature instead
                  </Button>
                </div>
              ) : (
                <ContractSignaturePad onChange={setSignatureData} />
              )}
            </div>
            <DialogFooter>
              <Button variant="outline" onClick={() => setSignOpen(false)}>
                Cancel
              </Button>
              <Button
                disabled={
                  signMutation.isPending ||
                  (!usingSaved && !signatureData) ||
                  !signerName.trim()
                }
                onClick={confirmSign}
              >
                {signMutation.isPending ? (
                  <Loader2 className="size-4 animate-spin" />
                ) : usingSaved ? (
                  "Approve & sign"
                ) : (
                  "Confirm signature"
                )}
              </Button>
            </DialogFooter>
          </DialogContent>
        </Dialog>
      </div>
    </div>
  );
}
