import { useEffect, useMemo, useState } from "react";
import { Box, Button, FileButton, Group, Select, Stack, Text } from "@mantine/core";
import { Eye, FileText, FileUp, Upload } from "lucide-react";
import { isViewable } from "@edr/ui-common";

import { useUploadGlDocuments } from "@/hooks/contracts/useContracts";
import { useFileViewer } from "@/hooks/useFileViewer";
import { ActionShell } from "./ActionShell";

/**
 * GL post-booking document slots. The fieldname (value) maps server-side to a
 * doc-triggered milestone in gl-operations.service.ts — uploading auto-advances
 * the matching milestone.
 */
const GL_DOC_SLOTS = [
  { value: "delivery_order", label: "Delivery Order (DO)" },
  { value: "release_order", label: "Release Order (RO)" },
  { value: "t1_transport_document", label: "T1 Transport Document" },
  { value: "import_release", label: "Import Release" },
  { value: "full_in_interchange", label: "Full-in Interchange" },
  { value: "final_declaration", label: "Final Declaration" },
];

export function GlDocumentUploadCard({ bookingId }: { bookingId: string }) {
  const upload = useUploadGlDocuments(bookingId);
  const [slot, setSlot] = useState<string | null>(GL_DOC_SLOTS[0].value);
  const [file, setFile] = useState<File | null>(null);
  const { view, viewer } = useFileViewer();

  const submit = () => {
    if (!slot || !file) return;
    upload.mutate({ [slot]: file });
    setFile(null);
  };

  return (
    <ActionShell
      icon={FileUp}
      title="GL documents"
      subtitle="Upload DO, RO, T1, release, interchange — advances milestones."
    >
      <Stack gap="sm">
        <Select
          label="Document type"
          data={GL_DOC_SLOTS}
          value={slot}
          onChange={setSlot}
          size="sm"
          allowDeselect={false}
        />
        <Group justify="space-between" wrap="nowrap">
          <FileButton onChange={setFile} accept="application/pdf,image/*">
            {(props) => (
              <Button
                {...props}
                variant="light"
                color="gray"
                size="compact-sm"
                leftSection={<Upload size={14} />}
              >
                {file ? file.name : "Choose file"}
              </Button>
            )}
          </FileButton>
          <Button
            size="compact-sm"
            color="edr-green"
            loading={upload.isPending}
            disabled={!file || !slot}
            onClick={submit}
          >
            Upload
          </Button>
        </Group>
        {file ? (
          <StagedFilePreview file={file} onPreview={view} />
        ) : (
          <Text size="xs" c="dimmed">
            PDF or image. The matching milestone completes on upload.
          </Text>
        )}
      </Stack>
      {viewer}
    </ActionShell>
  );
}

/**
 * A compact preview chip for the GL file staged for upload: an image thumbnail
 * (or a glyph) and a Preview button that opens the file in the shared viewer via
 * a local object URL (minted once, revoked on unmount).
 */
function StagedFilePreview({
  file,
  onPreview,
}: {
  file: File;
  onPreview: (f: { name: string; url: string; mimeType?: string | null }) => void;
}) {
  const url = useMemo(() => URL.createObjectURL(file), [file]);
  useEffect(() => () => URL.revokeObjectURL(url), [url]);

  const isImage =
    file.type.startsWith("image/") ||
    ["png", "jpg", "jpeg", "webp", "gif", "bmp", "svg"].includes(
      file.name.split(".").pop()?.toLowerCase() ?? "",
    );
  const canPreview = isViewable({ name: file.name, url, mimeType: file.type });

  return (
    <Group
      gap={10}
      wrap="nowrap"
      p={8}
      style={{
        borderRadius: 10,
        border: "1px dashed var(--mantine-color-edr-green-5)",
        background: "var(--mantine-color-edr-green-0)",
        minWidth: 0,
      }}
    >
      {isImage ? (
        <Box
          onClick={() => onPreview({ name: file.name, url, mimeType: file.type })}
          style={{
            width: 38,
            height: 38,
            flexShrink: 0,
            borderRadius: 8,
            overflow: "hidden",
            cursor: "pointer",
            border: "1px solid var(--mantine-color-gray-3)",
          }}
        >
          <img
            src={url}
            alt=""
            style={{ width: "100%", height: "100%", objectFit: "cover" }}
          />
        </Box>
      ) : (
        <Box
          c="edr-green"
          style={{
            width: 38,
            height: 38,
            flexShrink: 0,
            borderRadius: 8,
            display: "flex",
            alignItems: "center",
            justifyContent: "center",
            background: "var(--mantine-color-edr-green-1)",
          }}
        >
          <FileText size={17} />
        </Box>
      )}
      <Box style={{ minWidth: 0, flex: 1 }}>
        <Text size="xs" fw={700} c="edr-green">
          Ready to upload
        </Text>
        <Text size="xs" truncate>
          {file.name}
        </Text>
      </Box>
      {canPreview && (
        <Button
          size="compact-xs"
          variant="subtle"
          color="edr-green"
          leftSection={<Eye size={13} />}
          onClick={() => onPreview({ name: file.name, url, mimeType: file.type })}
        >
          Preview
        </Button>
      )}
    </Group>
  );
}
