import { useMemo, useState } from "react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
  Alert,
  Badge,
  Box,
  Button,
  Card,
  FileButton,
  Group,
  Loader,
  Progress,
  ScrollArea,
  Stack,
  Text,
  TextInput,
  Textarea,
  ThemeIcon,
  Tooltip,
} from "@mantine/core";
import {
  AlertCircle,
  CheckCircle2,
  Clock,
  Download,
  ExternalLink,
  FileText,
  Inbox,
  MessageSquareWarning,
  Search,
  ShieldCheck,
  Upload,
  X,
} from "lucide-react";
import toast from "react-hot-toast";
import type { Freight } from "@edr/types";

import { PageContainer } from "@/components/page/PageContainer";
import { PageHeader } from "@/components/page/PageHeader";
import { bookingsService } from "@/services/bookings.service";

const REVIEW_STATUS = "DOCUMENTS_UNDER_REVIEW";

export default function GlClearancePage() {
  const qc = useQueryClient();
  const [selectedId, setSelectedId] = useState<string | null>(null);
  const [search, setSearch] = useState("");

  // Bookings currently awaiting GL document review.
  const { data: list, isLoading } = useQuery({
    queryKey: ["gl-clearance", "list"],
    queryFn: () =>
      bookingsService.list({ status: REVIEW_STATUS, pageSize: 100 }),
  });

  const bookings = list?.items ?? [];
  const filtered = useMemo(() => {
    const q = search.trim().toLowerCase();
    if (!q) return bookings;
    return bookings.filter(
      (b) =>
        b.reference?.toLowerCase().includes(q) ||
        b.tradeDirection?.toLowerCase().includes(q) ||
        b.freightType?.toLowerCase().includes(q),
    );
  }, [bookings, search]);

  const activeId =
    selectedId && filtered.some((b) => b.id === selectedId)
      ? selectedId
      : (filtered[0]?.id ?? null);

  return (
    <PageContainer>
      <PageHeader
        title="Document Clearance"
        subtitle="Review customer documents, approve or raise a query, and finalize clearance."
        meta={
          <Badge
            variant="light"
            color="edr-green"
            radius="sm"
            leftSection={<ShieldCheck size={13} />}
          >
            {bookings.length} awaiting review
          </Badge>
        }
      />

      <div className="flex flex-col gap-5 lg:flex-row lg:items-start">
        {/* ── Review queue ─────────────────────────────────────────────── */}
        <Card
          withBorder
          shadow="sm"
          radius="lg"
          p="sm"
          className="w-full shrink-0 lg:w-[320px]"
        >
          <Group justify="space-between" align="center" mb="xs" px={4}>
            <Text fz="13px" fw={700} c="edr-text">
              Review queue
            </Text>
            <Badge size="sm" variant="default" radius="sm">
              {filtered.length}
            </Badge>
          </Group>

          <TextInput
            value={search}
            onChange={(e) => setSearch(e.currentTarget.value)}
            placeholder="Search reference…"
            size="xs"
            radius="md"
            mb="xs"
            leftSection={<Search size={14} />}
            rightSection={
              search ? (
                <X
                  size={14}
                  style={{ cursor: "pointer" }}
                  onClick={() => setSearch("")}
                />
              ) : null
            }
          />

          {isLoading ? (
            <Group justify="center" py="lg" gap={8}>
              <Loader size="xs" color="edr-green" />
              <Text fz="13px" c="dimmed">
                Loading…
              </Text>
            </Group>
          ) : filtered.length === 0 ? (
            <Stack align="center" gap={6} py="xl">
              <ThemeIcon variant="light" color="gray" radius="xl" size={40}>
                <Inbox size={20} />
              </ThemeIcon>
              <Text fz="13px" c="dimmed" ta="center">
                {search
                  ? "No bookings match your search."
                  : "Nothing awaiting document review."}
              </Text>
            </Stack>
          ) : (
            <ScrollArea.Autosize mah={620} type="hover" offsetScrollbars>
              <Stack gap={6}>
                {filtered.map((b) => (
                  <QueueItem
                    key={b.id}
                    booking={b}
                    active={b.id === activeId}
                    onSelect={() => setSelectedId(b.id)}
                  />
                ))}
              </Stack>
            </ScrollArea.Autosize>
          )}
        </Card>

        {/* ── Review panel ─────────────────────────────────────────────── */}
        <Box style={{ flex: 1, minWidth: 0 }}>
          {activeId ? (
            <ClearanceReviewPanel
              key={activeId}
              bookingId={activeId}
              onChanged={() =>
                qc.invalidateQueries({ queryKey: ["gl-clearance", "list"] })
              }
            />
          ) : (
            <EmptyPanel />
          )}
        </Box>
      </div>
    </PageContainer>
  );
}

/** A single booking row in the left-hand review queue. */
function QueueItem({
  booking,
  active,
  onSelect,
}: {
  booking: Freight.IBooking;
  active: boolean;
  onSelect: () => void;
}) {
  return (
    <Box
      component="button"
      type="button"
      onClick={onSelect}
      ta="left"
      p="xs"
      style={{
        cursor: "pointer",
        borderRadius: 12,
        border: "1px solid",
        borderColor: active
          ? "var(--mantine-color-edr-green-5)"
          : "var(--mantine-color-edr-border-6)",
        background: active
          ? "var(--mantine-color-edr-green-0)"
          : "var(--mantine-color-edr-card-6)",
        transition: "all 120ms ease",
      }}
    >
      <Group justify="space-between" wrap="nowrap" gap={8}>
        <Box style={{ minWidth: 0 }}>
          <Text fz="13.5px" fw={700} c="edr-text" truncate>
            {booking.reference}
          </Text>
          <Group gap={6} mt={3} wrap="nowrap">
            <Badge
              size="xs"
              variant="light"
              radius="sm"
              color={
                booking.tradeDirection === "IMPORT" ? "edr-blue" : "edr-accent"
              }
            >
              {booking.tradeDirection}
            </Badge>
            <Text fz="11px" c="edr-muted" truncate>
              {booking.freightType}
            </Text>
          </Group>
        </Box>
      </Group>
    </Box>
  );
}

function EmptyPanel() {
  return (
    <Card withBorder shadow="sm" radius="lg" p={48}>
      <Stack align="center" gap={10}>
        <ThemeIcon variant="light" color="edr-green" radius="xl" size={56}>
          <ShieldCheck size={28} />
        </ThemeIcon>
        <Text fw={700} c="edr-text">
          No booking selected
        </Text>
        <Text fz="13px" c="dimmed" ta="center" maw={320}>
          Pick a booking from the review queue to inspect its customer documents
          and start clearance.
        </Text>
      </Stack>
    </Card>
  );
}

function ClearanceReviewPanel({
  bookingId,
  onChanged,
}: {
  bookingId: string;
  onChanged: () => void;
}) {
  const qc = useQueryClient();
  const [queryNotes, setQueryNotes] = useState<Record<string, string>>({});
  const [openQuery, setOpenQuery] = useState<Record<string, boolean>>({});
  const [outputFiles, setOutputFiles] = useState<Record<string, File>>({});

  const { data: clearance, isLoading } = useQuery({
    queryKey: ["gl-clearance", bookingId],
    queryFn: () => bookingsService.getClearance(bookingId),
  });

  const refresh = () => {
    qc.invalidateQueries({ queryKey: ["gl-clearance", bookingId] });
    onChanged();
  };

  const reviewMutation = useMutation({
    mutationFn: (p: {
      fileKey: string;
      status: "APPROVED" | "QUERIED";
      note?: string;
    }) => bookingsService.reviewClearanceDocument(bookingId, p),
    onSuccess: (_d, p) => {
      toast.success(
        p.status === "APPROVED" ? "Document approved" : "Query sent to customer",
      );
      if (p.status === "QUERIED")
        setOpenQuery((o) => ({ ...o, [p.fileKey]: false }));
      refresh();
    },
    onError: () => toast.error("Could not update document"),
  });

  const outputMutation = useMutation({
    mutationFn: () =>
      bookingsService.uploadClearanceOutput(bookingId, outputFiles),
    onSuccess: () => {
      toast.success("Output documents uploaded");
      setOutputFiles({});
      refresh();
    },
    onError: () => toast.error("Upload failed"),
  });

  const finalizeMutation = useMutation({
    mutationFn: () => bookingsService.finalizeClearance(bookingId),
    onSuccess: () => {
      toast.success("Clearance finalized");
      refresh();
    },
    onError: (e) =>
      toast.error(
        e instanceof Error ? e.message : "Could not finalize clearance",
      ),
  });

  const customerDocs = useMemo(
    () => (clearance?.documents ?? []).filter((d) => d.uploadedBy === "customer"),
    [clearance],
  );
  const glDocs = useMemo(
    () => (clearance?.documents ?? []).filter((d) => d.uploadedBy === "gl"),
    [clearance],
  );

  // Review progress across the customer documents — drives the summary bar.
  const stats = useMemo(() => {
    const total = customerDocs.length;
    const approved = customerDocs.filter(
      (d) => d.reviewStatus === "APPROVED",
    ).length;
    const queried = customerDocs.filter(
      (d) => d.reviewStatus === "QUERIED",
    ).length;
    const pending = total - approved - queried;
    return { total, approved, queried, pending };
  }, [customerDocs]);

  if (isLoading || !clearance) {
    return (
      <Card withBorder shadow="sm" radius="lg" p={48}>
        <Group justify="center" gap={10}>
          <Loader size="sm" color="edr-green" />
          <Text c="dimmed">Loading clearance…</Text>
        </Group>
      </Card>
    );
  }

  const progressPct =
    stats.total === 0 ? 0 : Math.round((stats.approved / stats.total) * 100);

  return (
    <Stack gap="md">
      {/* ── Progress summary ───────────────────────────────────────────── */}
      <Card withBorder shadow="sm" radius="lg" p="lg">
        <Group justify="space-between" align="flex-start" mb="md">
          <Box>
            <Text fw={700} fz="15px" c="edr-text">
              Customer documents
            </Text>
            <Text fz="12.5px" c="dimmed" mt={2}>
              Approve each document, or open a query to tell the customer what to
              fix.
            </Text>
          </Box>
          {clearance.allApproved ? (
            <Badge
              variant="light"
              color="edr-green"
              radius="sm"
              size="lg"
              leftSection={<CheckCircle2 size={14} />}
            >
              All approved
            </Badge>
          ) : (
            <Badge
              variant="light"
              color="edr-blue"
              radius="sm"
              size="lg"
              leftSection={<Clock size={14} />}
            >
              Review pending
            </Badge>
          )}
        </Group>

        <Progress
          value={progressPct}
          color="edr-green"
          radius="xl"
          size="sm"
          mb="sm"
        />
        <Group gap="lg">
          <StatPill color="edr-green" label="Approved" value={stats.approved} />
          <StatPill color="red" label="Queried" value={stats.queried} />
          <StatPill color="edr-slate" label="Pending" value={stats.pending} />
          <Text fz="12.5px" c="dimmed" ml="auto">
            {stats.approved}/{stats.total} approved
          </Text>
        </Group>
      </Card>

      {/* ── Document review list ───────────────────────────────────────── */}
      <Stack gap={12}>
        {customerDocs.map((doc) => (
          <DocReviewCard
            key={`${doc.settingCode}:${doc.fileKey}`}
            doc={doc}
            note={queryNotes[doc.fileKey] ?? ""}
            queryOpen={openQuery[doc.fileKey] ?? false}
            onToggleQuery={(open) =>
              setOpenQuery((o) => ({ ...o, [doc.fileKey]: open }))
            }
            onNote={(v) => setQueryNotes((n) => ({ ...n, [doc.fileKey]: v }))}
            onApprove={() =>
              reviewMutation.mutate({ fileKey: doc.fileKey, status: "APPROVED" })
            }
            onQuery={() =>
              reviewMutation.mutate({
                fileKey: doc.fileKey,
                status: "QUERIED",
                note: queryNotes[doc.fileKey],
              })
            }
            busy={reviewMutation.isPending}
          />
        ))}
      </Stack>

      {/* ── Customs output documents (GL-supplied) ─────────────────────── */}
      {clearance.outputCode && (
        <Card withBorder shadow="sm" radius="lg" p="lg">
          <Group gap={8} mb="md">
            <ThemeIcon variant="light" color="edr-blue" radius="md" size={28}>
              <Upload size={15} />
            </ThemeIcon>
            <Text fw={700} c="edr-text">
              Customs output documents
            </Text>
          </Group>
          <Stack gap={10}>
            {glDocs.map((doc) => (
              <Group key={doc.fileKey} justify="space-between" wrap="nowrap">
                <Group gap={8} wrap="nowrap" style={{ minWidth: 0 }}>
                  <FileText size={16} color="var(--mantine-color-edr-blue-6)" />
                  <Text fz="13px" c="edr-text" truncate>
                    {doc.label}
                    {doc.required ? " *" : ""}
                  </Text>
                </Group>
                <Group gap={8} wrap="nowrap">
                  {doc.file ? (
                    <Tooltip label="Download">
                      <Box
                        component="a"
                        href={doc.file.url}
                        target="_blank"
                        rel="noreferrer"
                        c="edr-blue"
                        style={{ display: "flex" }}
                      >
                        <Download size={15} />
                      </Box>
                    </Tooltip>
                  ) : (
                    <Text fz="12px" c="edr-muted">
                      Not uploaded
                    </Text>
                  )}
                  <FileButton
                    onChange={(f) =>
                      f && setOutputFiles((o) => ({ ...o, [doc.fileKey]: f }))
                    }
                    accept="application/pdf,image/*"
                  >
                    {(props) => (
                      <Button
                        {...props}
                        size="compact-xs"
                        variant="light"
                        color="edr-green"
                        leftSection={<Upload size={13} />}
                      >
                        {outputFiles[doc.fileKey] ? "Selected" : "Upload"}
                      </Button>
                    )}
                  </FileButton>
                </Group>
              </Group>
            ))}
          </Stack>
          <Group justify="flex-end" mt="md">
            <Button
              variant="light"
              color="edr-green"
              radius="md"
              leftSection={<Upload size={15} />}
              disabled={Object.keys(outputFiles).length === 0}
              loading={outputMutation.isPending}
              onClick={() => outputMutation.mutate()}
            >
              Upload output documents
            </Button>
          </Group>
        </Card>
      )}

      {finalizeMutation.isError && (
        <Alert color="red" radius="md" icon={<AlertCircle size={16} />}>
          {finalizeMutation.error instanceof Error
            ? finalizeMutation.error.message
            : "Could not finalize clearance."}
        </Alert>
      )}

      {/* ── Finalize bar ───────────────────────────────────────────────── */}
      <Card withBorder shadow="sm" radius="lg" p="md">
        <Group justify="space-between" wrap="nowrap">
          <Text fz="12.5px" c="dimmed">
            {clearance.allApproved
              ? "All required documents are approved. You can finalize clearance."
              : "Approve every required document to unlock finalization."}
          </Text>
          <Button
            color="edr-green"
            radius="md"
            leftSection={<CheckCircle2 size={16} />}
            disabled={!clearance.allApproved}
            loading={finalizeMutation.isPending}
            onClick={() => finalizeMutation.mutate()}
          >
            Finalize clearance
          </Button>
        </Group>
      </Card>
    </Stack>
  );
}

function StatPill({
  color,
  label,
  value,
}: {
  color: string;
  label: string;
  value: number;
}) {
  return (
    <Group gap={6} wrap="nowrap">
      <Box
        style={{
          width: 8,
          height: 8,
          borderRadius: 999,
          background: `var(--mantine-color-${color}-6)`,
        }}
      />
      <Text fz="12.5px" c="edr-text" fw={600}>
        {value}
      </Text>
      <Text fz="12.5px" c="dimmed">
        {label}
      </Text>
    </Group>
  );
}

/** Visual treatment for each document review state. */
const STATUS_META: Record<
  Freight.DocumentReviewStatus,
  { label: string; color: string }
> = {
  APPROVED: { label: "Approved", color: "edr-green" },
  QUERIED: { label: "Queried", color: "red" },
  PENDING: { label: "Pending", color: "edr-slate" },
};

function DocReviewCard({
  doc,
  note,
  queryOpen,
  onToggleQuery,
  onNote,
  onApprove,
  onQuery,
  busy,
}: {
  doc: Freight.ClearanceDocument;
  note: string;
  queryOpen: boolean;
  onToggleQuery: (open: boolean) => void;
  onNote: (v: string) => void;
  onApprove: () => void;
  onQuery: () => void;
  busy: boolean;
}) {
  const status = doc.reviewStatus ?? "PENDING";
  const meta = STATUS_META[status];
  const hasFile = !!doc.file;

  return (
    <Card
      withBorder
      shadow="sm"
      radius="lg"
      p="md"
      style={{
        borderColor:
          status === "QUERIED"
            ? "var(--mantine-color-red-2)"
            : status === "APPROVED"
              ? "var(--mantine-color-edr-green-2)"
              : "var(--mantine-color-edr-border-6)",
      }}
    >
      <Group justify="space-between" align="flex-start" wrap="nowrap">
        <Group gap={12} wrap="nowrap" style={{ minWidth: 0 }}>
          <ThemeIcon
            variant="light"
            color={hasFile ? "edr-blue" : "gray"}
            radius="md"
            size={40}
          >
            <FileText size={19} />
          </ThemeIcon>
          <Box style={{ minWidth: 0 }}>
            <Text fz="14px" fw={700} c="edr-text" truncate>
              {doc.label}
              {doc.required ? " *" : ""}
            </Text>
            <Text fz="12px" c="edr-muted" truncate>
              {hasFile ? doc.file!.name : "Not uploaded by customer"}
            </Text>
          </Box>
        </Group>

        <Group gap={8} wrap="nowrap">
          <Badge variant="light" color={meta.color} radius="sm">
            {meta.label}
          </Badge>
          {hasFile && (
            <Tooltip label="Open document">
              <Button
                component="a"
                href={doc.file!.url}
                target="_blank"
                rel="noreferrer"
                size="compact-xs"
                variant="default"
                radius="md"
                leftSection={<ExternalLink size={13} />}
              >
                View
              </Button>
            </Tooltip>
          )}
        </Group>
      </Group>

      {/* Previously raised query — visible so staff see what was asked. */}
      {status === "QUERIED" && doc.note && (
        <Alert
          mt="sm"
          color="red"
          variant="light"
          radius="md"
          icon={<MessageSquareWarning size={15} />}
          p="xs"
        >
          <Text fz="12.5px" c="red.9">
            {doc.note}
          </Text>
        </Alert>
      )}

      {/* Action row — only when the customer actually uploaded a file. */}
      {hasFile && (
        <Box mt="sm">
          {!queryOpen ? (
            <Group justify="flex-end" gap={8}>
              <Button
                size="compact-sm"
                variant="light"
                color="red"
                radius="md"
                leftSection={<MessageSquareWarning size={14} />}
                disabled={busy}
                onClick={() => onToggleQuery(true)}
              >
                Open query
              </Button>
              <Button
                size="compact-sm"
                color="edr-green"
                radius="md"
                leftSection={<CheckCircle2 size={14} />}
                disabled={busy}
                onClick={onApprove}
              >
                Approve
              </Button>
            </Group>
          ) : (
            <Box
              p="sm"
              style={{
                borderRadius: 12,
                background: "var(--mantine-color-red-0)",
                border: "1px solid var(--mantine-color-red-2)",
              }}
            >
              <Group gap={6} mb={6}>
                <MessageSquareWarning
                  size={14}
                  color="var(--mantine-color-red-7)"
                />
                <Text fz="12.5px" fw={700} c="red.8">
                  Describe the problem for the customer
                </Text>
              </Group>
              <Textarea
                placeholder="e.g. The commercial invoice is missing the HS code and the totals don't match the packing list."
                value={note}
                onChange={(e) => onNote(e.currentTarget.value)}
                autosize
                minRows={2}
                radius="md"
                size="sm"
                autoFocus
              />
              <Group justify="flex-end" gap={8} mt={8}>
                <Button
                  size="compact-sm"
                  variant="subtle"
                  color="gray"
                  radius="md"
                  disabled={busy}
                  onClick={() => onToggleQuery(false)}
                >
                  Cancel
                </Button>
                <Button
                  size="compact-sm"
                  color="red"
                  radius="md"
                  leftSection={<MessageSquareWarning size={14} />}
                  loading={busy}
                  disabled={!note.trim()}
                  onClick={onQuery}
                >
                  Send query to customer
                </Button>
              </Group>
            </Box>
          )}
        </Box>
      )}
    </Card>
  );
}
