import { useState } from "react";
import { Alert, Box, Button, Group, Paper, Stack, Text, Textarea } from "@mantine/core";
import { AlertTriangle, ArrowRight, Download, MessageSquareWarning, PackageCheck, Receipt, Upload } from "lucide-react";
import { useQuery } from "@tanstack/react-query";
import toast from "react-hot-toast";
import type { Freight } from "@edr/types";

import { bookingStatusLabel } from "@/pages/bookings/booking-display";
import { ClearanceUploadedDocumentsPanel } from "@/components/contracts/ClearanceUploadedDocumentsPanel";
import { PortalFileDropzone } from "@/components/contracts/PortalFileDropzone";
import { contractsService } from "@/services/contracts.service";
import { fetchViewableFile, downloadStoredFile } from "@/services/files.service";
import { useFileViewer } from "@/hooks/useFileViewer";
import { BORDER, INK } from "./contract-ui";
import { ClearancePhaseStepper } from "./ClearancePhaseStepper";

function downloadWorkflowFile({ id, name }: { id: string; name: string }) {
  void downloadStoredFile(id, name);
}

export function ContractClearanceWorkflowBanner({
  contract,
}: {
  contract: Freight.IContract;
}) {
  const { view, viewer } = useFileViewer();
  const isPhased =
    contract.customsClearingEnabled && contract.contractKind === "ONE_TIME";

  const { data: clearance, refetch } = useQuery({
    queryKey: ["contract-clearance", contract.id],
    queryFn: () => contractsService.getClearance(contract.id),
    enabled: isPhased,
  });

  if (!isPhased || !clearance) return null;

  const dutyPaid = clearance.milestones?.some(
    (m) => m.milestoneCode === "DUTY_TAX_PAID" && m.status === "COMPLETED",
  );
  const dutyPending =
    clearance.dutyRequired &&
    clearance.dutyAdvice &&
    !dutyPaid;

  return (
    <>
      <Paper withBorder radius="lg" p="lg" style={{ borderColor: BORDER }}>
        <Stack gap="md">
          <Text fw={700} size="sm" style={{ color: INK }}>
            Clearance progress
          </Text>
          <ClearancePhaseStepper
            clearance={clearance}
            tradeDirection={contract.tradeDirection}
            compact
          />

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

          {clearance.nextAction?.actor === "CUSTOMER" ? (
            <Alert color="blue" variant="light">
              {clearance.nextAction.action}
            </Alert>
          ) : null}

          {/* Duty is disputed: GL owes a corrected advice, so the pay/upload
              panel is replaced by the waiting state until they re-send it. */}
          {clearance.dutyDispute ? (
            <Alert
              color="orange"
              variant="light"
              icon={<MessageSquareWarning size={16} />}
              title="Waiting for a corrected duty amount"
            >
              <Stack gap={4}>
                <Text fz={13}>
                  You asked GL Ethiopia to review the advised duty & tax. They
                  will send a corrected notice — you will be notified.
                </Text>
                <Text fz={12} c="dimmed" style={{ whiteSpace: "pre-wrap" }}>
                  Your message: {clearance.dutyDispute.note}
                </Text>
              </Stack>
            </Alert>
          ) : dutyPending && clearance.dutyAdvice ? (
            <DutyAdvicePanel
              dutyAdvice={clearance.dutyAdvice}
              contractId={contract.id}
              onUploaded={() => void refetch()}
              onPreview={view}
            />
          ) : null}

          <ClearanceUploadedDocumentsPanel
            embedded
            tradeDirection={contract.tradeDirection ?? "IMPORT"}
            files={clearance.workflowFiles ?? []}
            onView={view}
            onDownload={downloadWorkflowFile}
          />

          {clearance.linkedBookingId ? (
            <Alert color="green" variant="light" icon={<PackageCheck size={16} />}>
              <Stack gap={6}>
                <Text fz={13} fw={600} style={{ color: INK }}>
                  Shipment booking created
                  {clearance.linkedBookingReference
                    ? ` · ${clearance.linkedBookingReference}`
                    : ""}
                </Text>
                <Text fz={12} c="dimmed">
                  Global Logistics has created your shipment booking
                  {clearance.linkedBookingStatus
                    ? ` (${bookingStatusLabel(clearance.linkedBookingStatus).toLowerCase()})`
                    : ""}
                  . Track its progress from the booking.
                </Text>
                <Button
                  size="compact-sm"
                  variant="light"
                  color="green"
                  leftSection={<ArrowRight size={14} />}
                  component="a"
                  href={`/bookings/${clearance.linkedBookingId}`}
                  style={{ alignSelf: "flex-start" }}
                >
                  View shipment booking
                </Button>
              </Stack>
            </Alert>
          ) : clearance.bookingReady ? (
            <Alert color="green" variant="light">
              Clearance is complete. Global Logistics will create your shipment booking shortly.
            </Alert>
          ) : null}
        </Stack>
      </Paper>
      {viewer}
    </>
  );
}

function DutyAdvicePanel({
  dutyAdvice,
  contractId,
  onUploaded,
  onPreview,
}: {
  dutyAdvice: NonNullable<Freight.ContractClearanceView["dutyAdvice"]>;
  contractId: string;
  onUploaded: () => void;
  onPreview: (file: { name: string; url: string; mimeType?: string | null }) => void;
}) {
  const [file, setFile] = useState<File | null>(null);
  const [loading, setLoading] = useState(false);
  // Accept → pay and upload the slip. Query → say what is wrong and send it
  // back to GL Ethiopia for a corrected notice.
  const [disputing, setDisputing] = useState(false);
  const [disputeNote, setDisputeNote] = useState("");
  const [sendingDispute, setSendingDispute] = useState(false);

  return (
    <Paper
      withBorder
      radius="lg"
      p="md"
      style={{
        borderColor: "#F5D9A8",
        background: "linear-gradient(160deg, #FFFBF0 0%, #FFFFFF 70%)",
      }}
    >
      <Stack gap="md">
        <Group gap={8} wrap="nowrap">
          <Box
            style={{
              width: 32,
              height: 32,
              borderRadius: 8,
              display: "flex",
              alignItems: "center",
              justifyContent: "center",
              background: "#FFF3D6",
              color: "#C77F09",
            }}
          >
            <Receipt size={16} />
          </Box>
          <Text fw={700} fz={14} style={{ color: INK }}>
            Duty / tax payment
          </Text>
        </Group>

        <Paper withBorder radius="md" p="sm" bg="#fff">
          <Text fz={13} style={{ color: INK }}>
            Amount due:{" "}
            <strong>
              {dutyAdvice.amount.toLocaleString()} {dutyAdvice.currency}
            </strong>
            {dutyAdvice.declarationSerial
              ? ` · Payment code: ${dutyAdvice.declarationSerial}`
              : null}
          </Text>
          {dutyAdvice.noticeFile ? (
            <Group gap={8} mt={8}>
              <Button
                size="compact-xs"
                variant="light"
                color="orange"
                leftSection={<Download size={14} />}
                component="button"
                type="button"
                onClick={() =>
                  void downloadStoredFile(
                    dutyAdvice.noticeFile!.id,
                    dutyAdvice.noticeFile!.name,
                  )
                }
              >
                Download duty notice
              </Button>
              <Button
                size="compact-xs"
                variant="subtle"
                color="gray"
                onClick={() =>
                  void fetchViewableFile(
                    dutyAdvice.noticeFile!.id,
                    dutyAdvice.noticeFile!.name,
                  ).then(onPreview)
                }
              >
                Preview notice
              </Button>
            </Group>
          ) : null}
        </Paper>

        {disputing ? (
          <Stack gap="sm">
            <Text fz={13} c="dimmed">
              Tell GL Ethiopia what is wrong with this amount. They will review
              and send a corrected notice.
            </Text>
            <Textarea
              label="What needs correcting?"
              placeholder="e.g. the declared value is wrong — the invoice total is 412,000 ETB"
              value={disputeNote}
              onChange={(e) => setDisputeNote(e.currentTarget.value)}
              autosize
              minRows={3}
            />
            <Group gap="sm" grow>
              <Button
                variant="default"
                onClick={() => {
                  setDisputing(false);
                  setDisputeNote("");
                }}
              >
                Back
              </Button>
              <Button
                color="orange"
                loading={sendingDispute}
                disabled={!disputeNote.trim()}
                onClick={async () => {
                  setSendingDispute(true);
                  try {
                    await contractsService.disputeContractDuty(
                      contractId,
                      disputeNote.trim(),
                    );
                    toast.success("Sent back to GL Ethiopia for correction");
                    setDisputing(false);
                    setDisputeNote("");
                    onUploaded();
                  } catch (e) {
                    toast.error(e instanceof Error ? e.message : "Could not send");
                  } finally {
                    setSendingDispute(false);
                  }
                }}
              >
                Send for correction
              </Button>
            </Group>
          </Stack>
        ) : (
          <>
            <Text fz={13} c="dimmed">
              Pay the amount above, then upload your payment slip so clearance can
              continue. If the amount looks wrong, ask GL Ethiopia to correct it
              before paying.
            </Text>

            <PortalFileDropzone
              label="Payment slip"
              description="Upload proof of duty/tax payment (PDF or image)."
              value={file}
              onChange={setFile}
              onPreview={onPreview}
            />

            <Button
              color="orange"
              loading={loading}
              disabled={!file}
              leftSection={<Upload size={16} />}
              fullWidth
              onClick={async () => {
                if (!file) return;
                setLoading(true);
                try {
                  await contractsService.uploadContractDutySlip(contractId, file);
                  toast.success("Payment slip uploaded");
                  setFile(null);
                  onUploaded();
                } catch (e) {
                  toast.error(e instanceof Error ? e.message : "Upload failed");
                } finally {
                  setLoading(false);
                }
              }}
            >
              Accept & submit payment slip
            </Button>

            <Button
              variant="subtle"
              color="orange"
              leftSection={<MessageSquareWarning size={15} />}
              fullWidth
              onClick={() => setDisputing(true)}
            >
              Request a change to this amount
            </Button>
          </>
        )}
      </Stack>
    </Paper>
  );
}
