import { useMemo, useState } from "react";
import {
  Alert,
  Badge,
  Button,
  FileInput,
  Group,
  Modal,
  NumberInput,
  Paper,
  Select,
  Stack,
  Stepper,
  Text,
  Textarea,
} from "@mantine/core";
import { DateInput } from "@mantine/dates";
import {
  AlertTriangle,
  CheckCircle2,
  FileText,
  PackageCheck,
  Receipt,
  Ship,
  Train,
  Truck,
  Upload,
} from "lucide-react";
import type { Freight } from "@edr/types";
import toast from "react-hot-toast";

import { SectionCard } from "@/components/bookings/detail/SectionCard";
import { PhasedFileDropzone } from "@/components/contracts/PhasedFileDropzone";
import {
  TransitPermitMultiUpload,
  type TransitPermitUploadedRow,
} from "@/components/contracts/TransitPermitMultiUpload";
import {
  findWorkflowFile,
  PhasedUploadedFileRow,
} from "@/components/contracts/PhasedUploadedFileRow";
import {
  DeclarationStep,
  StepStatus,
  isBookingMilestoneDone,
  isMilestoneDone,
  type ClearanceViewLike,
  type MilestoneRow,
} from "@/components/contracts/PhasedClearanceActionPanel";
import { contractsService } from "@/services/contracts.service";
import { bookingsService } from "@/services/bookings.service";

/** Today as `yyyy-MM-dd` in the browser's local zone (a DateInput `minDate`). */
function todayISODate(): string {
  const now = new Date();
  const tz = now.getTimezoneOffset() * 60000;
  return new Date(now.getTime() - tz).toISOString().slice(0, 10);
}

/**
 * Export customs flow, ordered per the stakeholder process:
 * customer docs → RO (DJ) → declaration (ET, auto-releases) → create booking (ET)
 * → payment + wagons → transport document / T1 (ET) → train to Djibouti
 * → accept T1 (DJ, one button after arrival) → gate pass (DJ)
 * → final invoice (DJ) + customer slip + GL confirm.
 */
export function computeExportActiveStep(
  clearance: ClearanceViewLike,
  bookingMilestones: MilestoneRow[],
  bookingCreated: boolean,
): number {
  const released = Boolean(clearance.bookingReady || clearance.operationReady);
  if (!isMilestoneDone(clearance.milestones, "DOCUMENTS_APPROVED")) return 0;
  if (!isMilestoneDone(clearance.milestones, "RELEASE_ORDER_SECURED")) return 1;
  if (!isMilestoneDone(clearance.milestones, "DECLARED") || !released) return 2;
  if (!bookingCreated) return 3;
  if (
    !isBookingMilestoneDone(bookingMilestones, "FREIGHT_PAYMENT_SETTLED") ||
    !(
      isBookingMilestoneDone(bookingMilestones, "WAGON_ALLOCATED") ||
      clearance.train?.wagonAllocated
    )
  ) {
    return 4;
  }
  if (!isBookingMilestoneDone(bookingMilestones, "EXPORT_TRANSPORT_ISSUED")) return 5;
  if (!clearance.train?.arrivedAt) return 6;
  if (!clearance.t1Closed) return 7;
  if (!clearance.gatepassGranted) return 8;
  if (clearance.finalInvoice?.status !== "PAID") return 9;
  return 10;
}

export function exportTransitFilesFromWorkflow(
  workflowFiles: Freight.ClearanceWorkflowFile[],
): TransitPermitUploadedRow[] {
  return workflowFiles
    .filter(
      (f) =>
        f.category === "transit" &&
        f.code.toLowerCase().startsWith("export_transport_document") &&
        f.file,
    )
    .map((f) => ({
      code: f.code,
      label: f.label,
      file: f.file!,
    }));
}

export function ExportClearanceStepper({
  contractId,
  bookingId,
  clearance,
  workflowFiles = [],
  showEt,
  canEt,
  showDj,
  canDj,
  onChanged,
  bookingCreateHref,
  onViewFile,
  onDownloadFile,
  useUploadModals = false,
  onUploadRoRequest,
  bookingCreated = false,
  bookingMilestones = [],
}: {
  contractId?: string;
  bookingId?: string;
  clearance: ClearanceViewLike;
  workflowFiles?: Freight.ClearanceWorkflowFile[];
  showEt: boolean;
  canEt: boolean;
  showDj: boolean;
  canDj: boolean;
  onChanged?: () => void;
  bookingCreateHref?: string;
  onViewFile?: (file: { name: string; url: string }) => void;
  onDownloadFile?: (file: { id: string; name: string }) => void;
  useUploadModals?: boolean;
  onUploadRoRequest?: () => void;
  bookingCreated?: boolean;
  bookingMilestones?: MilestoneRow[];
}) {
  // Pre-booking actions (RO, declaration, release) target the contract when one
  // is present; GENERAL customs bookings run the same flow keyed on the booking.
  const isBooking = Boolean(bookingId) && !contractId;
  const entityId = contractId ?? bookingId ?? "";
  // The booking that carries the post-booking steps (gate pass, T1, invoice).
  const actionBookingId = clearance.linkedBookingId ?? bookingId ?? null;
  // Per-booking GENERAL clearance runs on a bare instance that only becomes a
  // real booking once GL completes it — the caller's bookingCreated prop carries
  // that signal, so a booking-keyed view must NOT count as "created" by itself
  // (it would lock GL Ethiopia out of the declaration step right after the RO).
  const effectiveBookingCreated =
    bookingCreated || Boolean(clearance.linkedBookingId);

  const activeStep = useMemo(
    () => computeExportActiveStep(clearance, bookingMilestones, effectiveBookingCreated),
    [clearance, bookingMilestones, effectiveBookingCreated],
  );

  const released = Boolean(clearance.bookingReady || clearance.operationReady);
  const declared = isMilestoneDone(clearance.milestones, "DECLARED");
  const paymentSettled = isBookingMilestoneDone(bookingMilestones, "FREIGHT_PAYMENT_SETTLED");
  const wagonAllocated =
    isBookingMilestoneDone(bookingMilestones, "WAGON_ALLOCATED") ||
    Boolean(clearance.train?.wagonAllocated);
  const transportIssued = isBookingMilestoneDone(bookingMilestones, "EXPORT_TRANSPORT_ISSUED");

  return (
    <Stack gap="md">
      {clearance.roHold && clearance.roHoldReason ? (
        <Alert color="orange" icon={<AlertTriangle size={16} />} title="Release Order on hold">
          {clearance.roHoldReason}
        </Alert>
      ) : null}

      {clearance.nextAction ? (
        <Alert color="blue" variant="light" title="Next step">
          <Text size="sm">
            <strong>{clearance.nextAction.actor.replace("_", " ")}</strong> —{" "}
            {clearance.nextAction.action}
          </Text>
        </Alert>
      ) : null}

      <Paper withBorder radius="md" p="md">
        <Text fw={600} size="sm" mb="md">
          Export customs clearance
        </Text>
        <Stepper
          active={activeStep}
          orientation="vertical"
          size="sm"
          iconSize={26}
          allowNextStepsSelect={false}
        >
          <Stepper.Step
            label="Customer documents"
            description="Review and approve in the panel on the left"
            icon={
              isMilestoneDone(clearance.milestones, "DOCUMENTS_APPROVED") ? (
                <CheckCircle2 size={14} />
              ) : undefined
            }
          >
            <StepStatus
              done={isMilestoneDone(clearance.milestones, "DOCUMENTS_APPROVED")}
              pendingLabel="Approve every required customer document."
              doneLabel="All required documents approved."
            />
          </Stepper.Step>

          <Stepper.Step
            label="Release Order"
            description="GL Djibouti uploads RO + vessel date"
            icon={<Ship size={14} />}
          >
            {showDj && canDj ? (
              useUploadModals ? (
                <ReleaseOrderActions
                  entityId={entityId}
                  isBooking={isBooking}
                  clearance={clearance}
                  workflowFiles={workflowFiles}
                  onUploadRoRequest={onUploadRoRequest}
                  onChanged={onChanged}
                  onViewFile={onViewFile}
                  onDownloadFile={onDownloadFile}
                />
              ) : (
                <ReleaseOrderCard
                  entityId={entityId}
                  isBooking={isBooking}
                  clearance={clearance}
                  onChanged={onChanged}
                />
              )
            ) : (
              <Stack gap="sm">
                {findWorkflowFile(workflowFiles, "release_order") ? (
                  <PhasedUploadedFileRow
                    label="Release Order"
                    file={findWorkflowFile(workflowFiles, "release_order")!}
                    onView={onViewFile}
                    onDownload={onDownloadFile}
                  />
                ) : null}
                {clearance.vesselDepartureDate ? (
                  <Text size="sm" c="dimmed">
                    Vessel departure:{" "}
                    {new Date(clearance.vesselDepartureDate).toLocaleDateString()}
                  </Text>
                ) : null}
                <StepStatus
                  done={isMilestoneDone(clearance.milestones, "RELEASE_ORDER_SECURED")}
                  pendingLabel="Waiting for GL Djibouti to upload the Release Order."
                  doneLabel="Release Order secured."
                />
              </Stack>
            )}
          </Stepper.Step>

          <Stepper.Step
            label="Customs declaration"
            description="GL Ethiopia uploads — releases the export"
            icon={declared ? <CheckCircle2 size={14} /> : <FileText size={14} />}
          >
            {showEt && canEt && !effectiveBookingCreated && (activeStep >= 2 || declared) ? (
              <Stack gap="sm">
                <DeclarationStep
                  entityId={entityId}
                  isBooking={isBooking}
                  replaceMode={declared}
                  workflowFiles={workflowFiles}
                  onChanged={onChanged}
                  onViewFile={onViewFile}
                  onDownloadFile={onDownloadFile}
                />
                {declared && !released ? (
                  <ConfirmExportReleaseFallback
                    entityId={entityId}
                    isBooking={isBooking}
                    onChanged={onChanged}
                  />
                ) : null}
              </Stack>
            ) : (
              <StepStatus
                done={declared && released}
                pendingLabel="Waiting for GL Ethiopia to upload the customs declaration."
                doneLabel="Declaration uploaded — export released."
              />
            )}
          </Stepper.Step>

          <Stepper.Step
            label="Create booking"
            description="GL Ethiopia books for the customer"
            icon={<Ship size={14} />}
          >
            {released && bookingCreateHref && !effectiveBookingCreated && showEt && canEt ? (
              <SectionCard icon={Ship} title="Create booking" accent="edr-green">
                <Text size="sm" c="dimmed" mb="sm">
                  Export is released. Create the shipment booking for the customer.
                </Text>
                <Button component="a" href={bookingCreateHref} color="edr-green">
                  Create shipment booking
                </Button>
              </SectionCard>
            ) : (
              <StepStatus
                done={effectiveBookingCreated}
                pendingLabel={
                  released
                    ? "Ready — GL Ethiopia creates the shipment booking."
                    : "Complete the declaration step first."
                }
                doneLabel="Shipment booking created."
              />
            )}
          </Stepper.Step>

          <Stepper.Step
            label="Payment & wagon allocation"
            description="Customer pays; operations allocates wagons"
            icon={<Receipt size={14} />}
          >
            <Stack gap="xs">
              <StepStatus
                done={paymentSettled}
                pendingLabel="Waiting for the customer to pay freight charges."
                doneLabel="Freight payment settled."
              />
              <StepStatus
                done={wagonAllocated}
                pendingLabel="Waiting for operations to allocate wagons."
                doneLabel="Wagons allocated."
              />
            </Stack>
          </Stepper.Step>

          <Stepper.Step
            label="Transport document"
            description="GL Ethiopia uploads after wagon allocation"
            icon={transportIssued ? <CheckCircle2 size={14} /> : <Upload size={14} />}
          >
            {showEt && canEt && actionBookingId && wagonAllocated ? (
              <ExportTransitPermitStep
                bookingId={actionBookingId}
                workflowFiles={workflowFiles}
                onChanged={onChanged}
                onViewFile={onViewFile}
                onDownloadFile={onDownloadFile}
              />
            ) : (
              <Stack gap="sm">
                {exportTransitFilesFromWorkflow(workflowFiles).map((row) => (
                  <PhasedUploadedFileRow
                    key={row.code}
                    label={row.label}
                    file={row.file}
                    onView={onViewFile}
                    onDownload={onDownloadFile}
                    compact
                  />
                ))}
                <StepStatus
                  done={transportIssued}
                  pendingLabel={
                    wagonAllocated
                      ? "Waiting for GL Ethiopia to upload the transport document."
                      : "Available once wagons are allocated."
                  }
                  doneLabel="Transport document uploaded."
                />
              </Stack>
            )}
          </Stepper.Step>

          <Stepper.Step
            label="Train to Djibouti"
            description="Departure and arrival"
            icon={<Train size={14} />}
          >
            <Stack gap="xs">
              <StepStatus
                done={Boolean(clearance.train?.departedAt)}
                pendingLabel="Waiting for the train to depart."
                doneLabel={`Departed ${
                  clearance.train?.departedAt
                    ? new Date(clearance.train.departedAt).toLocaleString()
                    : ""
                }`}
              />
              <StepStatus
                done={Boolean(clearance.train?.arrivedAt)}
                pendingLabel="Waiting for arrival at Djibouti."
                doneLabel={`Arrived ${
                  clearance.train?.arrivedAt
                    ? new Date(clearance.train.arrivedAt).toLocaleString()
                    : ""
                }`}
              />
            </Stack>
          </Stepper.Step>

          <Stepper.Step
            label="Accept T1"
            description="GL Djibouti closes once the train arrives"
            icon={clearance.t1Closed ? <CheckCircle2 size={14} /> : <PackageCheck size={14} />}
          >
            <AcceptT1Step
              bookingId={actionBookingId}
              clearance={clearance}
              transportIssued={transportIssued}
              workflowFiles={workflowFiles}
              canAct={showDj && canDj}
              onChanged={onChanged}
              onViewFile={onViewFile}
              onDownloadFile={onDownloadFile}
            />
          </Stepper.Step>

          <Stepper.Step
            label="Gate pass"
            description="Secured on the train schedule after arrival"
            icon={clearance.gatepassGranted ? <CheckCircle2 size={14} /> : <Truck size={14} />}
          >
            <GatepassStep clearance={clearance} />
          </Stepper.Step>

          <Stepper.Step
            label="Final invoice & payment"
            description="GL Djibouti invoices after offload; customer pays"
            icon={
              clearance.finalInvoice?.status === "PAID" ? (
                <CheckCircle2 size={14} />
              ) : (
                <Receipt size={14} />
              )
            }
          >
            <FinalInvoiceStep
              bookingId={actionBookingId}
              clearance={clearance}
              canDjAct={showDj && canDj}
              canConfirm={(showDj && canDj) || (showEt && canEt)}
              onChanged={onChanged}
              onViewFile={onViewFile}
              onDownloadFile={onDownloadFile}
            />
          </Stepper.Step>
        </Stepper>
      </Paper>
    </Stack>
  );
}

/** Legacy in-flight contracts: declaration done before auto-release existed. */
function ConfirmExportReleaseFallback({
  entityId,
  isBooking,
  onChanged,
}: {
  entityId: string;
  isBooking: boolean;
  onChanged?: () => void;
}) {
  const [loading, setLoading] = useState(false);
  return (
    <Button
      variant="light"
      color="edr-green"
      loading={loading}
      leftSection={<PackageCheck size={16} />}
      onClick={async () => {
        setLoading(true);
        try {
          if (isBooking) {
            await bookingsService.confirmExportRelease(entityId);
          } else {
            await contractsService.confirmExportRelease(entityId);
          }
          toast.success("Export released — ready for booking");
          onChanged?.();
        } catch (e) {
          toast.error(e instanceof Error ? e.message : "Failed");
        } finally {
          setLoading(false);
        }
      }}
    >
      Confirm export release
    </Button>
  );
}

/**
 * Gate pass status, read-only. Secured on the train schedule's "Save as
 * Secured" action (train-scheduling-v2) — clearance no longer grants it directly.
 */
function GatepassStep({ clearance }: { clearance: ClearanceViewLike }) {
  const scheduleId = clearance.train?.scheduleId ?? null;

  if (clearance.gatepassGranted) {
    return (
      <StepStatus
        done
        pendingLabel=""
        doneLabel={`Gate pass secured${
          clearance.gatepassAt ? ` · ${new Date(clearance.gatepassAt).toLocaleString()}` : ""
        }`}
      />
    );
  }

  const arrived = Boolean(clearance.train?.arrivedAt);

  return (
    <Stack gap="sm">
      <StepStatus
        done={false}
        pendingLabel={
          arrived
            ? "Train arrived — secure the gate pass on the train schedule."
            : "Available once the train arrives at Djibouti."
        }
        doneLabel=""
      />
      {scheduleId ? (
        <Button
          component="a"
          href={`/dashboard/operations/train-scheduling-v2/${scheduleId}`}
          variant="light"
          color="edr-green"
          leftSection={<Truck size={16} />}
        >
          Secure gate pass on train schedule
        </Button>
      ) : null}
    </Stack>
  );
}

function AcceptT1Step({
  bookingId,
  clearance,
  transportIssued,
  workflowFiles = [],
  canAct,
  onChanged,
  onViewFile,
  onDownloadFile,
}: {
  bookingId: string | null;
  clearance: ClearanceViewLike;
  transportIssued: boolean;
  workflowFiles?: Freight.ClearanceWorkflowFile[];
  canAct: boolean;
  onChanged?: () => void;
  onViewFile?: (file: { name: string; url: string }) => void;
  onDownloadFile?: (file: { id: string; name: string }) => void;
}) {
  const [loading, setLoading] = useState(false);
  const files = exportTransitFilesFromWorkflow(workflowFiles);
  const arrived = Boolean(clearance.train?.arrivedAt);

  return (
    <Stack gap="sm">
      {files.map((row) => (
        <PhasedUploadedFileRow
          key={row.code}
          label={row.label}
          file={row.file}
          onView={onViewFile}
          onDownload={onDownloadFile}
          compact
        />
      ))}
      {clearance.t1Closed ? (
        <StepStatus
          done
          pendingLabel=""
          doneLabel={`T1 accepted and closed${
            clearance.t1ClosedAt ? ` · ${new Date(clearance.t1ClosedAt).toLocaleString()}` : ""
          }`}
        />
      ) : (
        <>
          <StepStatus
            done={false}
            pendingLabel={
              !transportIssued
                ? "Waiting for the transport document."
                : arrived
                  ? "Train arrived — GL Djibouti accepts (closes) the T1."
                  : "Available once the train arrives at Djibouti."
            }
            doneLabel=""
          />
          {canAct && bookingId ? (
            <Button
              color="edr-green"
              loading={loading}
              disabled={!transportIssued || !arrived}
              leftSection={<PackageCheck size={16} />}
              onClick={async () => {
                setLoading(true);
                try {
                  await contractsService.closeT1(bookingId);
                  toast.success("T1 accepted and closed");
                  onChanged?.();
                } catch (e) {
                  toast.error(e instanceof Error ? e.message : "Failed");
                } finally {
                  setLoading(false);
                }
              }}
            >
              Accept &amp; close T1
            </Button>
          ) : null}
        </>
      )}
    </Stack>
  );
}

function FinalInvoiceStep({
  bookingId,
  clearance,
  canDjAct,
  canConfirm,
  onChanged,
  onViewFile,
  onDownloadFile,
}: {
  bookingId: string | null;
  clearance: ClearanceViewLike;
  canDjAct: boolean;
  canConfirm: boolean;
  onChanged?: () => void;
  onViewFile?: (file: { name: string; url: string }) => void;
  onDownloadFile?: (file: { id: string; name: string }) => void;
}) {
  const [opened, setOpened] = useState(false);
  const [amount, setAmount] = useState<number | string>("");
  const [currency, setCurrency] = useState("ETB");
  const [description, setDescription] = useState("");
  const [file, setFile] = useState<File | null>(null);
  const [sending, setSending] = useState(false);
  const [confirming, setConfirming] = useState(false);

  const invoice = clearance.finalInvoice ?? null;
  const paid = invoice?.status === "PAID";

  // Export: OFFLOADED is a DJ doc milestone that may never be recorded, so the
  // secured gate pass is enough to open invoicing. Sending an invoice is optional.
  if (!clearance.offloaded && !clearance.gatepassGranted && !invoice) {
    return (
      <StepStatus
        done={false}
        pendingLabel="Waiting for cargo offload (handled in operations)."
        doneLabel=""
      />
    );
  }

  return (
    <Stack gap="sm">
      {invoice ? (
        <Paper withBorder radius="md" p="sm">
          <Group justify="space-between" wrap="nowrap">
            <div>
              <Text fw={700} size="sm">
                {invoice.invoiceNumber}
              </Text>
              <Text size="sm" c="dimmed">
                {invoice.totalAmount.toLocaleString()} {invoice.currency}
                {invoice.description ? ` — ${invoice.description}` : ""}
              </Text>
            </div>
            <Badge color={paid ? "edr-green" : "yellow"} variant="light">
              {invoice.status}
            </Badge>
          </Group>
        </Paper>
      ) : null}

      {invoice?.invoiceFile ? (
        <PhasedUploadedFileRow
          label="Final Invoice"
          file={invoice.invoiceFile}
          onView={onViewFile}
          onDownload={onDownloadFile}
          compact
        />
      ) : null}
      {invoice?.slipFile ? (
        <PhasedUploadedFileRow
          label="Customer payment slip"
          file={invoice.slipFile}
          onView={onViewFile}
          onDownload={onDownloadFile}
          compact
        />
      ) : null}

      {paid ? (
        <StepStatus
          done
          pendingLabel=""
          doneLabel={`Payment confirmed${
            invoice?.confirmedAt ? ` · ${new Date(invoice.confirmedAt).toLocaleString()}` : ""
          }`}
        />
      ) : invoice ? (
        <>
          <StepStatus
            done={false}
            pendingLabel={
              invoice.slipFile
                ? "Payment slip attached — confirm to settle the invoice."
                : "Waiting for the customer to pay and attach the payment slip."
            }
            doneLabel=""
          />
          {canConfirm && bookingId && invoice.slipFile ? (
            <Button
              color="edr-green"
              loading={confirming}
              leftSection={<CheckCircle2 size={16} />}
              onClick={async () => {
                setConfirming(true);
                try {
                  await contractsService.confirmFinalInvoicePaid(bookingId);
                  toast.success("Payment confirmed — invoice settled");
                  onChanged?.();
                } catch (e) {
                  toast.error(e instanceof Error ? e.message : "Failed");
                } finally {
                  setConfirming(false);
                }
              }}
            >
              Confirm payment received
            </Button>
          ) : null}
        </>
      ) : canDjAct && bookingId ? (
        <>
          <Text size="sm" c="dimmed">
            Send the final invoice to the customer if post-arrival charges apply (optional).
          </Text>
          <Button
            color="edr-green"
            leftSection={<Receipt size={16} />}
            onClick={() => setOpened(true)}
          >
            Send invoice
          </Button>
          <Modal
            opened={opened}
            onClose={() => setOpened(false)}
            title={<Text fw={700}>Send final invoice</Text>}
            radius="md"
            size="md"
          >
            <Stack gap="md">
              <Group grow align="flex-start">
                <NumberInput
                  label="Amount"
                  placeholder="0.00"
                  value={amount}
                  onChange={setAmount}
                  min={0}
                  thousandSeparator=","
                  required
                />
                <Select
                  label="Currency"
                  data={["ETB", "USD"]}
                  value={currency}
                  onChange={(v) => setCurrency(v ?? "ETB")}
                />
              </Group>
              <Textarea
                label="Description"
                placeholder="What the invoice bills for"
                value={description}
                onChange={(e) => setDescription(e.currentTarget.value)}
                minRows={2}
              />
              <PhasedFileDropzone
                label="Invoice document"
                description="Any file type."
                accept="*/*"
                value={file}
                onChange={setFile}
                onPreview={onViewFile}
              />
              <Group justify="flex-end">
                <Button variant="default" onClick={() => setOpened(false)} disabled={sending}>
                  Cancel
                </Button>
                <Button
                  color="edr-green"
                  loading={sending}
                  disabled={amount === "" || Number(amount) <= 0 || !file}
                  leftSection={<Upload size={16} />}
                  onClick={async () => {
                    if (!file) return;
                    setSending(true);
                    try {
                      await contractsService.sendFinalInvoice(bookingId, {
                        amount: Number(amount),
                        currency,
                        description: description.trim() || undefined,
                        file,
                      });
                      toast.success("Final invoice sent to the customer");
                      setOpened(false);
                      onChanged?.();
                    } catch (e) {
                      toast.error(e instanceof Error ? e.message : "Failed");
                    } finally {
                      setSending(false);
                    }
                  }}
                >
                  Send invoice
                </Button>
              </Group>
            </Stack>
          </Modal>
        </>
      ) : (
        <StepStatus
          done={false}
          pendingLabel="Waiting for GL Djibouti to send the final invoice."
          doneLabel=""
        />
      )}
    </Stack>
  );
}

export function ReleaseOrderActions({
  entityId,
  isBooking,
  clearance,
  workflowFiles = [],
  onUploadRoRequest,
  onChanged,
  onViewFile,
  onDownloadFile,
}: {
  entityId: string;
  isBooking: boolean;
  clearance: ClearanceViewLike & { vesselDepartureDate?: string | null };
  workflowFiles?: Freight.ClearanceWorkflowFile[];
  onUploadRoRequest?: () => void;
  onChanged?: () => void;
  onViewFile?: (file: { name: string; url: string }) => void;
  onDownloadFile?: (file: { id: string; name: string }) => void;
}) {
  const [amendLoading, setAmendLoading] = useState(false);
  const roFile = findWorkflowFile(workflowFiles, "release_order");

  return (
    <Paper withBorder radius="md" p="md">
      <Text fw={600} size="sm" mb="sm">
        Release Order
      </Text>
      <Stack gap="sm">
        {roFile ? (
          <PhasedUploadedFileRow
            label="Release Order"
            file={roFile}
            onView={onViewFile}
            onDownload={onDownloadFile}
          />
        ) : null}
        {clearance.vesselDepartureDate ? (
          <Text size="sm" c="dimmed">
            Vessel departure:{" "}
            {new Date(clearance.vesselDepartureDate).toLocaleDateString()}
          </Text>
        ) : null}
        <Group>
          {onUploadRoRequest ? (
            <Button color="edr-green" leftSection={<Upload size={16} />} onClick={onUploadRoRequest}>
              {roFile ? "Replace RO" : "Upload RO"}
            </Button>
          ) : null}
          <Button
            variant="light"
            color="orange"
            loading={amendLoading}
            onClick={async () => {
              setAmendLoading(true);
              try {
                if (isBooking) {
                  await bookingsService.requestRoAmendment(
                    entityId,
                    "Port amendment requested — vessel window too short.",
                  );
                } else {
                  await contractsService.requestRoAmendment(
                    entityId,
                    "Port amendment requested — vessel window too short.",
                  );
                }
                toast.success("Amendment request recorded");
                onChanged?.();
              } catch (e) {
                toast.error(e instanceof Error ? e.message : "Failed");
              } finally {
                setAmendLoading(false);
              }
            }}
          >
            Request amendment
          </Button>
        </Group>
      </Stack>
    </Paper>
  );
}

export function ReleaseOrderCard({
  entityId,
  isBooking,
  clearance,
  onChanged,
}: {
  entityId: string;
  isBooking: boolean;
  clearance: ClearanceViewLike & { vesselDepartureDate?: string | null };
  onChanged?: () => void;
}) {
  const [file, setFile] = useState<File | null>(null);
  const [vesselDate, setVesselDate] = useState<Date | null>(
    clearance.vesselDepartureDate ? new Date(clearance.vesselDepartureDate) : null,
  );
  const [loading, setLoading] = useState(false);
  const [amendLoading, setAmendLoading] = useState(false);
  const minVesselDate = useMemo(todayISODate, []);

  return (
    <Paper withBorder radius="md" p="md">
      <Text fw={600} size="sm" mb="sm">
        Release Order
      </Text>
      <Stack gap="sm">
        <FileInput label="Release Order" value={file} onChange={setFile} size="sm" />
        <DateInput
          label="Vessel departure date"
          value={vesselDate}
          onChange={(v) => setVesselDate(v ? new Date(v) : null)}
          minDate={minVesselDate}
          size="sm"
        />
        <Group>
          <Button
            color="edr-green"
            loading={loading}
            disabled={!file || !vesselDate}
            onClick={async () => {
              if (!file || !vesselDate) return;
              setLoading(true);
              try {
                const iso = vesselDate.toISOString().slice(0, 10);
                const result = isBooking
                  ? await bookingsService.uploadReleaseOrder(entityId, file, iso)
                  : await contractsService.uploadReleaseOrder(entityId, file, iso);
                if (result.hold) {
                  toast.error(result.holdReason ?? "Vessel date too soon");
                } else {
                  toast.success("Release Order accepted");
                }
                onChanged?.();
              } catch (e) {
                toast.error(e instanceof Error ? e.message : "Upload failed");
              } finally {
                setLoading(false);
              }
            }}
          >
            Upload RO
          </Button>
          <Button
            variant="light"
            color="orange"
            loading={amendLoading}
            onClick={async () => {
              setAmendLoading(true);
              try {
                if (isBooking) {
                  await bookingsService.requestRoAmendment(
                    entityId,
                    "Port amendment requested — vessel window too short.",
                  );
                } else {
                  await contractsService.requestRoAmendment(
                    entityId,
                    "Port amendment requested — vessel window too short.",
                  );
                }
                toast.success("Amendment request recorded");
                onChanged?.();
              } catch (e) {
                toast.error(e instanceof Error ? e.message : "Failed");
              } finally {
                setAmendLoading(false);
              }
            }}
          >
            Request amendment
          </Button>
        </Group>
      </Stack>
    </Paper>
  );
}

export function ExportTransitPermitStep({
  bookingId,
  workflowFiles = [],
  replaceMode = false,
  onChanged,
  onViewFile,
  onDownloadFile,
}: {
  bookingId: string;
  workflowFiles?: Freight.ClearanceWorkflowFile[];
  replaceMode?: boolean;
  onChanged?: () => void;
  onViewFile?: (file: { name: string; url: string }) => void;
  onDownloadFile?: (file: { id: string; name: string }) => void;
}) {
  const uploaded = exportTransitFilesFromWorkflow(workflowFiles);
  const hasUploaded = uploaded.length > 0;

  if (hasUploaded && !replaceMode) {
    return (
      <Stack gap="sm">
        <Text size="sm" fw={700}>
          Transport document
        </Text>
        {uploaded.map((row) => (
          <PhasedUploadedFileRow
            key={row.code}
            label={row.label}
            file={row.file}
            onView={onViewFile}
            onDownload={onDownloadFile}
          />
        ))}
      </Stack>
    );
  }

  return (
    <TransitPermitMultiUpload
      title="Transport document"
      replaceMode={replaceMode || hasUploaded}
      uploaded={uploaded}
      fileFieldPrefix="export_transport_document"
      onViewFile={onViewFile}
      onDownloadFile={onDownloadFile}
      onSubmit={async (payload) => {
        try {
          await contractsService.uploadTransportDocument(bookingId, payload);
          toast.success(replaceMode ? "Transport document updated" : "Transport document uploaded");
          onChanged?.();
        } catch (e) {
          toast.error(e instanceof Error ? e.message : "Upload failed");
          throw e;
        }
      }}
    />
  );
}
