import {
  Alert,
  Box,
  Button,
  FileButton,
  Group,
  Stack,
  Text,
  TextInput,
} from "@mantine/core";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
  AlertCircle,
  CheckCircle2,
  Clock,
  Download,
  FileText,
  Plus,
  Upload,
} from "lucide-react";
import { useMemo, useState } from "react";
import { useNavigate } from "react-router-dom";

import { api } from "@/services/api";
import type { Freight } from "@edr/types";

import { CardTitle, SectionCard } from "./layout";
import { IconSquare } from "./Documents";

const GREEN = "#0A6F4D";

function StatusPill({ doc }: { doc: Freight.ClearanceDocument }) {
  if (doc.reviewStatus === "APPROVED") {
    return (
      <Group gap={6} c={GREEN}>
        <CheckCircle2 size={15} />
        <Text fz="12px" fw={600} c={GREEN}>
          Approved
        </Text>
      </Group>
    );
  }
  if (doc.reviewStatus === "QUERIED") {
    return (
      <Group gap={6} c="#C0392B">
        <AlertCircle size={15} />
        <Text fz="12px" fw={600} c="#C0392B">
          Queried
        </Text>
      </Group>
    );
  }
  if (doc.file) {
    return (
      <Group gap={6} c="#2E5B96">
        <Clock size={15} />
        <Text fz="12px" fw={600} c="#2E5B96">
          Pending review
        </Text>
      </Group>
    );
  }
  return (
    <Text fz="12px" fw={600} c="#9AA8B5">
      Not uploaded
    </Text>
  );
}

/**
 * Customer-facing clearance section: shows the resolved document grid, lets the
 * customer (re)upload pending/queried documents plus ad-hoc named documents, and
 * proceed to operation once Global Logistics marks the booking CLEARANCE_READY.
 */
export function ClearanceCard({ booking }: { booking: Freight.IBooking }) {
  const queryClient = useQueryClient();
  const navigate = useNavigate();
  const status = booking.status as string;

  const { data: clearance, isLoading } = useQuery(
    api.bookings.getClearance.queryOptions({ input: { id: booking.id } }),
  );

  // Pending uploads keyed by fileKey, plus ad-hoc rows (label + file).
  const [pending, setPending] = useState<Record<string, File>>({});
  const [adHoc, setAdHoc] = useState<Array<{ name: string; file: File | null }>>(
    [],
  );

  const refresh = () => {
    queryClient.invalidateQueries({
      queryKey: api.bookings.getClearance.queryKey({ id: booking.id }),
    });
    queryClient.invalidateQueries({
      queryKey: api.bookings.get.queryKey({ id: booking.id }),
    });
  };

  const uploadMutation = useMutation({
    ...api.bookings.submitClearanceDocuments.mutationOptions(),
    onSuccess: () => {
      setPending({});
      setAdHoc([]);
      refresh();
    },
  });

  const proceedMutation = useMutation({
    ...api.bookings.proceedToOperation.mutationOptions(),
    onSuccess: () => refresh(),
  });

  // Only the customer-input documents are uploadable here; GL output docs are
  // shown read-only.
  const customerDocs = useMemo(
    () => (clearance?.documents ?? []).filter((d) => d.uploadedBy === "customer"),
    [clearance],
  );
  const glDocs = useMemo(
    () => (clearance?.documents ?? []).filter((d) => d.uploadedBy === "gl"),
    [clearance],
  );

  if (status === "OPERATION_REQUESTED") {
    return (
      <SectionCard>
        <CardTitle>Operation</CardTitle>
        <Alert color="teal" radius="md" icon={<CheckCircle2 size={18} />} mt="sm">
          Operation requested. An operator will take your shipment forward.
        </Alert>
      </SectionCard>
    );
  }

  if (isLoading || !clearance) {
    return (
      <SectionCard>
        <CardTitle>Clearance documents</CardTitle>
        <Text fz="13px" c="dimmed" mt="sm">
          Loading clearance…
        </Text>
      </SectionCard>
    );
  }

  const isReady = status === "CLEARANCE_READY";
  const canUpload =
    status === "AWAITING_DOCUMENTS" || status === "DOCUMENTS_UNDER_REVIEW";

  function handleSubmit() {
    const files: Record<string, File | null> = { ...pending };
    adHoc.forEach((row, i) => {
      if (row.file) files[`custom_${Date.now()}_${i}`] = row.file;
    });
    if (Object.keys(files).length === 0) return;
    uploadMutation.mutate({ id: booking.id, files });
  }

  return (
    <SectionCard>
      <Group justify="space-between" align="center" mb="md">
        <CardTitle>Clearance documents</CardTitle>
        {clearance.includesCustoms && (
          <Text fz="12px" fw={600} c="#9AA8B5">
            Customs clearance
          </Text>
        )}
      </Group>

      {isReady ? (
        <Alert color="teal" radius="md" icon={<CheckCircle2 size={18} />} mb="md">
          Clearance is ready. You can now proceed to operation.
        </Alert>
      ) : status === "DOCUMENTS_UNDER_REVIEW" ? (
        <Alert color="blue" radius="md" icon={<Clock size={18} />} mb="md">
          Global Logistics is reviewing your documents. Queried documents below
          need to be re-uploaded.
        </Alert>
      ) : (
        <Alert color="yellow" radius="md" icon={<AlertCircle size={18} />} mb="md">
          Upload the documents below to start the clearance review.
        </Alert>
      )}

      <Stack gap={10}>
        {customerDocs.map((doc) => (
          <Box
            key={doc.fileKey}
            className="rounded-xl"
            style={{ border: "1px solid #E6ECF2", padding: 12 }}
          >
            <Group justify="space-between" align="center" wrap="nowrap">
              <Group gap={10} wrap="nowrap" style={{ minWidth: 0 }}>
                <Box c="#2E5B96">
                  <FileText size={18} />
                </Box>
                <Box style={{ minWidth: 0 }}>
                  <Text fz="13.5px" fw={600} c="#10202F" truncate>
                    {doc.label}
                    {doc.required ? " *" : ""}
                  </Text>
                  {doc.file && (
                    <Text fz="12px" c="dimmed" truncate>
                      {doc.file.name}
                    </Text>
                  )}
                </Box>
              </Group>
              <Group gap={10} wrap="nowrap">
                <StatusPill doc={doc} />
                {doc.file && (
                  <IconSquare href={doc.file.url} icon={<Download size={15} />} />
                )}
                {canUpload && doc.reviewStatus !== "APPROVED" && (
                  <FileButton
                    onChange={(f) =>
                      f && setPending((p) => ({ ...p, [doc.fileKey]: f }))
                    }
                    accept="application/pdf,image/*"
                  >
                    {(props) => (
                      <Button
                        {...props}
                        size="compact-xs"
                        variant="light"
                        color="edr-green"
                        leftSection={<Upload size={13} />}
                      >
                        {pending[doc.fileKey] ? "Selected" : "Upload"}
                      </Button>
                    )}
                  </FileButton>
                )}
              </Group>
            </Group>
            {doc.reviewStatus === "QUERIED" && doc.note && (
              <Text fz="12px" c="#C0392B" mt={6}>
                Query: {doc.note}
              </Text>
            )}
            {pending[doc.fileKey] && (
              <Text fz="12px" c={GREEN} mt={6}>
                Ready to upload: {pending[doc.fileKey].name}
              </Text>
            )}
          </Box>
        ))}
      </Stack>

      {/* GL output documents (read-only to the customer). */}
      {glDocs.length > 0 && (
        <>
          <Text fz="12.5px" fw={700} c="#10202F" mt="lg" mb={8}>
            Customs output documents
          </Text>
          <Stack gap={8}>
            {glDocs.map((doc) => (
              <Group
                key={doc.fileKey}
                justify="space-between"
                wrap="nowrap"
                className="rounded-xl"
                style={{ border: "1px solid #E6ECF2", padding: 10 }}
              >
                <Text fz="13px" c="#10202F" truncate>
                  {doc.label}
                </Text>
                {doc.file ? (
                  <IconSquare href={doc.file.url} icon={<Download size={15} />} />
                ) : (
                  <Text fz="12px" c="#9AA8B5">
                    Pending
                  </Text>
                )}
              </Group>
            ))}
          </Stack>
        </>
      )}

      {/* Ad-hoc / additional documents. */}
      {canUpload && (
        <Box mt="lg">
          <Group justify="space-between" align="center" mb={8}>
            <Text fz="12.5px" fw={700} c="#10202F">
              Additional documents
            </Text>
            <Button
              size="compact-xs"
              variant="light"
              color="edr-green"
              leftSection={<Plus size={13} />}
              onClick={() => setAdHoc((r) => [...r, { name: "", file: null }])}
            >
              Add document
            </Button>
          </Group>
          <Stack gap={8}>
            {adHoc.map((row, i) => (
              <Group key={i} gap={8} wrap="nowrap">
                <TextInput
                  placeholder="Document name"
                  value={row.name}
                  onChange={(e) =>
                    setAdHoc((rows) =>
                      rows.map((r, j) =>
                        j === i ? { ...r, name: e.currentTarget.value } : r,
                      ),
                    )
                  }
                  style={{ flex: 1 }}
                  radius="md"
                />
                <FileButton
                  onChange={(f) =>
                    setAdHoc((rows) =>
                      rows.map((r, j) => (j === i ? { ...r, file: f } : r)),
                    )
                  }
                  accept="application/pdf,image/*"
                >
                  {(props) => (
                    <Button {...props} variant="default" radius="md">
                      {row.file ? row.file.name.slice(0, 14) : "Choose file"}
                    </Button>
                  )}
                </FileButton>
              </Group>
            ))}
          </Stack>
        </Box>
      )}

      {uploadMutation.isError && (
        <Alert color="red" radius="md" icon={<AlertCircle size={16} />} mt="md">
          {uploadMutation.error instanceof Error
            ? uploadMutation.error.message
            : "Upload failed. Please try again."}
        </Alert>
      )}

      <Group justify="flex-end" mt="lg" gap="sm">
        {canUpload && (
          <Button
            color="edr-green"
            radius="md"
            leftSection={<Upload size={16} />}
            onClick={handleSubmit}
            loading={uploadMutation.isPending}
            disabled={
              Object.keys(pending).length === 0 &&
              !adHoc.some((r) => r.file)
            }
          >
            Submit documents
          </Button>
        )}
        {isReady && (
          <Button
            color="edr-green"
            radius="md"
            leftSection={<CheckCircle2 size={16} />}
            onClick={() =>
              proceedMutation.mutate(
                { id: booking.id },
                { onSuccess: () => navigate(`/bookings/${booking.id}`) },
              )
            }
            loading={proceedMutation.isPending}
          >
            Proceed to operation
          </Button>
        )}
      </Group>
    </SectionCard>
  );
}
