import {
  Alert,
  Box,
  Group,
  Stack,
  Text,
} from "@mantine/core";
import {
  AlertCircle,
  CheckCircle2,
  Clock,
  Download,
  Eye,
  FileText,
} from "lucide-react";

import type { Freight } from "@edr/types";
import { isViewable } from "@edr/ui-common";

import { IconSquare } from "../BookingDetailPage/components/Documents";
import {
  ClearanceAdHocUploadSection,
} from "@/components/contracts/ClearanceAdHocUploadSection";
import { ClearanceDocumentUploadCard } from "@/components/contracts/ClearanceDocumentUploadCard";
import { fetchViewableFile, downloadStoredFile } from "@/services/files.service";
import { useFileViewer } from "@/hooks/useFileViewer";
import { OperationDatePicker } from "./OperationDatePicker";
import { DayAvailabilityHint } from "./DayAvailabilityHint";
import type { ClearanceFlowController } from "./useClearanceFlow";

const BORDER = "#E6ECF2";

interface ClearanceFlowProps {
  booking: Freight.IBooking;
  flow: ClearanceFlowController;
  /**
   * Rendered at the bottom of the flow (the submit / proceed buttons). Host
   * supplies this so the detail card and the modal can place actions in their
   * own footer chrome.
   */
  footer?: React.ReactNode;
}

/**
 * Presentational body of the customer clearance/operation flow: the required
 * document grid (with re-upload of pending/queried docs), GL output documents,
 * ad-hoc documents, and the shipment-day picker once CLEARANCE_READY.
 *
 * All state lives in the `flow` controller (see `useClearanceFlow`) so this can
 * be dropped into either the booking detail card or the home-page action modal.
 */
export function ClearanceFlow({ booking, flow, footer }: ClearanceFlowProps) {
  const {
    clearance,
    customerDocs,
    glDocs,
    isReady,
    needsCompletion,
    awaitingGlCompletion,
    canUpload,
    isInitialUpload,
    status,
    pending,
    adHoc,
    missingRequired,
    stagePending,
    addAdHocRow,
    removeAdHocRow,
    setAdHocName,
    setAdHocFile,
    scheduledDate,
    setScheduledDate,
    uploadMutation,
    proceedMutation,
  } = flow;
  const { view, viewer } = useFileViewer();

  if (!clearance) return null;

  return (
    <Stack gap={0}>
      {isReady ? (
        <Alert color="teal" radius="md" icon={<CheckCircle2 size={18} />} mb="md">
          {needsCompletion
            ? "Clearance is finalized. Complete your booking now — enter the cargo details and pick a shipment day inside an open booking window."
            : awaitingGlCompletion
              ? "Customs clearance is complete. Global Logistics is completing your booking (cargo details and shipment day) — you will be notified when payment is due."
              : clearance.includesCustoms
                ? "Customs clearance is complete and your cleared documents are available below. You can now proceed to operation."
                : "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">
          {clearance.includesCustoms
            ? "Global Logistics is reviewing your documents and will clear your shipment. Only re-upload the documents flagged with a query below — approved documents stay as they are."
            : "Our team is reviewing your documents. Only re-upload the documents flagged with a query below — approved documents stay as they are."}
        </Alert>
      ) : (
        <Alert color="yellow" radius="md" icon={<AlertCircle size={18} />} mb="md">
          {clearance.includesCustoms
            ? "Upload every required document customs needs (marked *) to start the review. Global Logistics will clear your shipment and return the cleared documents here."
            : "Upload every required clearance document (marked *) below to start the review."}
        </Alert>
      )}

      {isInitialUpload && missingRequired.length > 0 && (
        <Alert color="yellow" variant="light" radius="md" mb="md" p="xs">
          <Text fz="12px" c="#9A5B00">
            Still required:{" "}
            {missingRequired.map((d) => d.label).join(", ")}
          </Text>
        </Alert>
      )}

      <Stack gap="md">
        <Box>
          <Text fz={13} fw={700} c="#10202F">
            Your clearance documents
          </Text>
          <Text fz={12} c="dimmed" mt={4}>
            Upload each required document below. Items marked * are mandatory.
          </Text>
        </Box>
        {customerDocs.map((doc) => (
          <ClearanceDocumentUploadCard
            key={doc.fileKey}
            label={doc.label}
            required={doc.required}
            reviewStatus={doc.reviewStatus}
            note={doc.note}
            uploadedFile={doc.file}
            stagedFile={pending[doc.fileKey] ?? null}
            canUpload={canUpload}
            onStageFile={
              canUpload && doc.reviewStatus !== "APPROVED"
                ? (file) => stagePending(doc.fileKey, file)
                : undefined
            }
            onPreview={view}
          />
        ))}
      </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 ${BORDER}`, padding: 10 }}
              >
                <Group gap={10} wrap="nowrap" style={{ minWidth: 0 }}>
                  <Box c="#2E5B96">
                    <FileText size={18} />
                  </Box>
                  <Text fz="13px" c="#10202F" truncate>
                    {doc.label}
                  </Text>
                </Group>
                {doc.file ? (
                  <Group gap={8} wrap="nowrap">
                    {isViewable({
                      name: doc.file.name,
                      url: "",
                    }) && (
                      <IconSquare
                        icon={<Eye size={15} />}
                        onClick={() =>
                          void fetchViewableFile(
                            doc.file!.id,
                            doc.file!.name,
                          ).then(view)
                        }
                      />
                    )}
                    <IconSquare
                      icon={<Download size={15} />}
                      onClick={() =>
                        void downloadStoredFile(doc.file!.id, doc.file!.name)
                      }
                    />
                  </Group>
                ) : (
                  <Text fz="12px" c="#9AA8B5">
                    Pending
                  </Text>
                )}
              </Group>
            ))}
          </Stack>
        </>
      )}

      {canUpload ? (
        <ClearanceAdHocUploadSection
          rows={adHoc}
          onAdd={addAdHocRow}
          onRemove={removeAdHocRow}
          onNameChange={setAdHocName}
          onFileChange={setAdHocFile}
          onPreview={view}
        />
      ) : null}

      {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>
      )}

      {isReady && !needsCompletion && !awaitingGlCompletion && (
        <Box mt="lg">
          <Text fz="13px" fw={700} c="#10202F" mb={6}>
            Choose your shipment day
          </Text>
          <Text fz="12px" c="dimmed" mb="sm">
            Only days with a scheduled departure that can carry your cargo type
            can be selected. The operations team assigns the specific train for
            that day.
          </Text>
          <OperationDatePicker
            originYardId={booking.originYard?.id}
            destinationYardId={booking.destinationYard?.id}
            bookingId={booking.id}
            value={scheduledDate}
            onChange={setScheduledDate}
          />
          {scheduledDate && (
            <DayAvailabilityHint
              bookingId={booking.id}
              date={scheduledDate}
              tradeDirection={booking.tradeDirection}
            />
          )}
        </Box>
      )}

      {proceedMutation.isError && (
        <Alert color="red" radius="md" icon={<AlertCircle size={16} />} mt="md">
          {proceedMutation.error instanceof Error
            ? proceedMutation.error.message
            : "Could not request the operation. Please try again."}
        </Alert>
      )}

      {footer}
      {viewer}
    </Stack>
  );
}
