import { ActionIcon, Box, Button, Group, Stack, Text } from "@mantine/core";
import { useMutation, useQuery } from "@tanstack/react-query";
import { CreditCard, Download, FileText, Receipt } from "lucide-react";
import { useState } from "react";
import toast from "react-hot-toast";

import { paymentsService, type PaymentMethod } from "@/services/payments.service";
import {
  warehouseInvoicesService,
  type PortalWarehouseInvoice,
} from "@/services/warehouse-invoices.service";
import { saveBlob } from "@/utils/download";

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

/** Warehouse fee invoices the customer can still settle online. */
const PAYABLE_STATUSES = new Set(["ISSUED", "PARTIALLY_PAID"]);
const isPayable = (inv: PortalWarehouseInvoice) =>
  PAYABLE_STATUSES.has(inv.status) && Number(inv.balanceAmount ?? 0) > 0;

const money = (amount: number | string | null | undefined, currency: string) =>
  `${Number(amount ?? 0).toLocaleString()} ${currency}`;

const STATUS_STYLE: Record<string, { bg: string; fg: string }> = {
  DRAFT: { bg: "#EEF2F6", fg: "#64748B" },
  ISSUED: { bg: "#FEF3E2", fg: "#B45309" },
  PARTIALLY_PAID: { bg: "#FEF9E7", fg: "#A16207" },
  PAID: { bg: "#E6F7EF", fg: "#0A6F4D" },
  CANCELLED: { bg: "#EEF2F6", fg: "#64748B" },
};

function StatusPill({ status }: { status: string }) {
  const s = STATUS_STYLE[status] ?? { bg: "#EEF2F6", fg: "#64748B" };
  return (
    <Box
      style={{
        display: "inline-flex",
        alignItems: "center",
        padding: "3px 9px",
        borderRadius: 999,
        background: s.bg,
        color: s.fg,
        fontSize: 11,
        fontWeight: 700,
        whiteSpace: "nowrap",
      }}
    >
      {status.replace(/_/g, " ")}
    </Box>
  );
}

/**
 * Warehouse fee invoices linked to this booking. Customers can pay outstanding
 * demurrage/storage invoices online (Telebirr/Waafi) so they can then sign the
 * delivery handover; paid invoices expose the receipt PDF. The backoffice cash
 * `/pay` (record-a-payment) path is unaffected. Renders nothing when the booking
 * has no warehouse fees. Carries `id="warehouse-payments"` so the invoice detail
 * page can deep-link here.
 */
export function WarehousePaymentsSection({ bookingId }: { bookingId: string }) {
  const { data: invoices = [] } = useQuery({
    queryKey: ["booking-warehouse-invoices", bookingId],
    queryFn: () => warehouseInvoicesService.listForBooking(bookingId),
  });

  const [payInvoice, setPayInvoice] = useState<PortalWarehouseInvoice | null>(null);

  const payMutation = useMutation({
    mutationFn: (method: PaymentMethod) => {
      if (!payInvoice) throw new Error("No invoice selected for payment.");
      return warehouseInvoicesService.payOnline(payInvoice.id, {
        method,
        platform: "web",
      });
    },
    onSuccess: (data, method) => {
      if (!payInvoice) return;
      // Redirect to the provider (or the fallback checkout page) — same as the
      // booking "Pay now" flow, so behaviour is identical everywhere.
      const redirectUrl =
        data?.clientAction?.type === "REDIRECT" && data.clientAction.url
          ? data.clientAction.url
          : paymentsService.checkoutUrlForInvoice({ invoiceId: payInvoice.id, method });
      window.location.href = redirectUrl;
    },
  });

  const payError = payMutation.isError
    ? payMutation.error instanceof Error
      ? payMutation.error.message
      : "Could not start payment. Please try again."
    : null;

  const closePayModal = () => {
    if (!payMutation.isPending) {
      setPayInvoice(null);
      payMutation.reset();
    }
  };

  if (invoices.length === 0) return null;

  const download = async (inv: PortalWarehouseInvoice) => {
    try {
      saveBlob(
        await warehouseInvoicesService.downloadDocument(inv.id),
        `warehouse-invoice-${inv.invoiceNumber}.pdf`,
      );
    } catch {
      toast.error("Warehouse invoice PDF isn't ready yet.");
    }
  };

  const downloadReceipt = async (inv: PortalWarehouseInvoice) => {
    try {
      saveBlob(
        await warehouseInvoicesService.downloadReceipt(inv.id),
        `warehouse-receipt-${inv.invoiceNumber}.pdf`,
      );
    } catch {
      toast.error("Receipt isn't available yet.");
    }
  };

  return (
    <SectionCard id="warehouse-payments">
      <Group justify="space-between" align="center" mb="md">
        <CardTitle>Warehouse payments</CardTitle>
        <Text fz="12.5px" fw={600} c="#9AA8B5">
          {invoices.length} {invoices.length === 1 ? "invoice" : "invoices"}
        </Text>
      </Group>
      <Stack gap={12}>
        {invoices.map((inv) => {
          const detail = [
            inv.invoiceType?.replace(/_/g, " "),
            inv.cargoDescription ??
              inv.containerNumber ??
              inv.inventoryReference ??
              undefined,
          ]
            .filter(Boolean)
            .join(" · ");
          return (
            <Group
              key={inv.id}
              justify="space-between"
              align="flex-start"
              wrap="nowrap"
              style={{
                border: "1px solid #EEF2F6",
                borderRadius: 12,
                padding: "12px 14px",
              }}
            >
              <Box style={{ minWidth: 0 }}>
                <Group gap={8} wrap="nowrap">
                  <Text fz="13.5px" fw={700} c="#10202F">
                    {inv.invoiceNumber}
                  </Text>
                  <StatusPill status={inv.status} />
                </Group>
                {detail && (
                  <Text fz="12px" c="#9AA8B5" mt={2}>
                    {detail}
                  </Text>
                )}
                <Text fz="12.5px" c="#6B7C8E" mt={4}>
                  Total {money(inv.totalAmount, inv.currency)} · Balance{" "}
                  {money(inv.balanceAmount, inv.currency)}
                </Text>
              </Box>
              <Group gap={6} wrap="nowrap">
                {isPayable(inv) && (
                  <Button
                    size="xs"
                    radius={10}
                    color="edr-green"
                    leftSection={<CreditCard size={14} />}
                    onClick={() => setPayInvoice(inv)}
                  >
                    Pay
                  </Button>
                )}
                {invoices.length > 1 && (
                  <>
                    <ActionIcon
                      variant="subtle"
                      color="gray"
                      aria-label="Download invoice"
                      onClick={() => download(inv)}
                    >
                      <Download size={16} />
                    </ActionIcon>
                    {Number(inv.paidAmount) > 0 && (
                      <ActionIcon
                        variant="subtle"
                        color="gray"
                        aria-label="Download receipt"
                        onClick={() => downloadReceipt(inv)}
                      >
                        <Receipt size={16} />
                      </ActionIcon>
                    )}
                  </>
                )}
              </Group>
            </Group>
          );
        })}
      </Stack>

      {/* Single invoice: a prominent download instead of a lone row icon. */}
      {invoices.length === 1 && (
        <>
          <Button
            fullWidth
            mt="md"
            variant="default"
            radius={10}
            leftSection={<FileText size={17} color="#475569" />}
            onClick={() => download(invoices[0])}
            styles={{
              root: { height: 46 },
              label: { fontSize: 13.5, fontWeight: 700, color: "#10202F" },
            }}
          >
            Download invoice
          </Button>
          {Number(invoices[0].paidAmount) > 0 && (
            <Button
              fullWidth
              mt={8}
              variant="subtle"
              color="gray"
              radius={10}
              leftSection={<Receipt size={17} />}
              onClick={() => downloadReceipt(invoices[0])}
              styles={{ root: { height: 42 }, label: { fontSize: 13, fontWeight: 700 } }}
            >
              Download receipt
            </Button>
          )}
        </>
      )}

      <PaymentMethodModal
        opened={payInvoice !== null}
        onClose={closePayModal}
        amountLabel={
          payInvoice ? money(payInvoice.balanceAmount, payInvoice.currency) : undefined
        }
        currency={payInvoice?.currency}
        onConfirm={(method) => payMutation.mutate(method)}
        processing={payMutation.isPending}
        error={payError}
      />
    </SectionCard>
  );
}
