import { useMemo, useState } from 'react';
import {
  ActionIcon,
  Badge,
  Button,
  Card,
  Divider,
  Group,
  Loader,
  Modal,
  NumberInput,
  Select,
  Stack,
  Table,
  Text,
  TextInput,
} from '@mantine/core';
import { Ban, CreditCard, Eye, Search } from 'lucide-react';
import { DataTable, type ColumnDef } from '@edr/ui-common';

import { PageContainer, PageHeader } from '@/components/page';
import { useMutation, useQuery } from '@tanstack/react-query';

import { api } from '@/services/api';
import { useToast } from '@/hooks/use-toast';
import {
  WAREHOUSE_INVOICE_STATUSES,
  type WarehouseFeeInvoice,
  type WarehouseInvoiceStatus,
} from '@/types/warehouse';

const STATUS_COLOR: Record<WarehouseInvoiceStatus, string> = {
  DRAFT: 'gray',
  ISSUED: 'orange',
  PARTIALLY_PAID: 'yellow',
  PAID: 'edr-green',
  CANCELLED: 'gray',
};

const fmt = (n: number, c: string) => `${Number(n).toLocaleString()} ${c}`;
const fmtDate = (d?: string | null) => (d ? new Date(d).toLocaleDateString() : '—');

export default function WarehouseInvoicesPage() {
  const [status, setStatus] = useState<WarehouseInvoiceStatus | null>(null);
  const [search, setSearch] = useState('');
  const [detailId, setDetailId] = useState<string | null>(null);

  const { data, isLoading } = useQuery(
    api.warehouses.invoices.queryOptions({
      input: { filter: status ? { status } : undefined },
    }),
  );
  const invoices = data ?? [];

  const filtered = useMemo(() => {
    const q = search.trim().toLowerCase();
    if (!q) return invoices;
    return invoices.filter((i) => [i.invoiceNumber, i.bookingId, i.customerId].join(' ').toLowerCase().includes(q));
  }, [invoices, search]);

  const invoiceColumns: ColumnDef<WarehouseFeeInvoice>[] = [
    {
      id: 'invoiceNumber',
      header: 'Invoice No',
      cell: ({ row }) => (
        <Text fw={600} size="sm">
          {row.original.invoiceNumber}
        </Text>
      ),
    },
    { id: 'type', header: 'Type', cell: ({ row }) => row.original.invoiceType.replace(/_/g, ' ') },
    { id: 'total', header: 'Total', cell: ({ row }) => fmt(row.original.totalAmount, row.original.currency) },
    { id: 'paid', header: 'Paid', cell: ({ row }) => fmt(row.original.paidAmount, row.original.currency) },
    {
      id: 'balance',
      header: 'Balance',
      cell: ({ row }) => fmt(row.original.balanceAmount, row.original.currency),
    },
    {
      id: 'status',
      header: 'Status',
      cell: ({ row }) => (
        <Badge variant="light" color={STATUS_COLOR[row.original.status]}>
          {row.original.status.replace(/_/g, ' ')}
        </Badge>
      ),
    },
    {
      id: 'issued',
      header: 'Issued',
      cell: ({ row }) => <Text size="xs">{fmtDate(row.original.issuedAt)}</Text>,
    },
    {
      id: 'actions',
      header: '',
      cell: ({ row }) => (
        <Group justify="flex-end" onClick={(e) => e.stopPropagation()}>
          <ActionIcon
            variant="subtle"
            color="gray"
            onClick={() => setDetailId(row.original.id)}
            title="View"
          >
            <Eye size={16} />
          </ActionIcon>
        </Group>
      ),
    },
  ];

  return (
    <PageContainer>
      <PageHeader
        title="Warehouse Fee Invoices"
        subtitle="Demurrage & storage invoices generated from warehouse fee rules."
      />

      <Card>
        <Group justify="space-between" mb="md" wrap="wrap">
            <TextInput
              placeholder="Search invoice no / booking / customer"
              leftSection={<Search size={16} />}
              value={search}
              onChange={(e) => setSearch(e.currentTarget.value)}
              w={320}
            />
            <Select
              placeholder="All statuses"
              data={WAREHOUSE_INVOICE_STATUSES.map((s) => ({ value: s, label: s.replace(/_/g, ' ') }))}
              value={status}
              onChange={(v) => setStatus((v as WarehouseInvoiceStatus) ?? null)}
              clearable
              w={200}
            />
          </Group>

        <DataTable
          columns={invoiceColumns}
          data={filtered}
          status={isLoading ? 'loading' : 'success'}
          emptyMessage="No invoices found."
          containerClassName="border-0 shadow-none"
        />
      </Card>

      <InvoiceDetailModal id={detailId} onClose={() => setDetailId(null)} />
    </PageContainer>
  );
}

function InvoiceDetailModal({ id, onClose }: { id: string | null; onClose: () => void }) {
  const { toast } = useToast();
  const { data: inv, isLoading } = useQuery(
    api.warehouses.invoice.queryOptions({
      input: { id: id ?? '' },
      enabled: Boolean(id),
    }),
  );
  const pay = useMutation(api.warehouses.payInvoice.mutationOptions());
  const cancel = useMutation(api.warehouses.cancelInvoice.mutationOptions());
  const [payAmount, setPayAmount] = useState<number | ''>('');

  const canPay = inv && (inv.status === 'ISSUED' || inv.status === 'PARTIALLY_PAID');

  const handlePay = async () => {
    if (!inv || !payAmount) return;
    try {
      await pay.mutateAsync({ id: inv.id, payload: { amount: Number(payAmount), method: 'MANUAL' } });
      toast({ title: 'Payment recorded' });
      setPayAmount('');
    } catch (e) {
      toast({ variant: 'destructive', title: 'Payment failed', description: (e as Error)?.message });
    }
  };

  const handleCancel = async () => {
    if (!inv) return;
    try {
      await cancel.mutateAsync(inv.id);
      toast({ title: 'Invoice cancelled' });
      onClose();
    } catch (e) {
      toast({ variant: 'destructive', title: 'Cancel failed', description: (e as Error)?.message });
    }
  };

  return (
    <Modal opened={Boolean(id)} onClose={onClose} title="Fee invoice" centered size="lg">
      {isLoading || !inv ? (
        <Group justify="center" py="xl"><Loader /></Group>
      ) : (
        <Stack gap="sm">
          <Group justify="space-between">
            <Text fw={700} size="lg">{inv.invoiceNumber}</Text>
            <Badge variant="light" color={STATUS_COLOR[inv.status]} size="lg">{inv.status.replace(/_/g, ' ')}</Badge>
          </Group>

          <Table withRowBorders={false} verticalSpacing={4}>
            <Table.Tbody>
              {(inv.items ?? []).map((it) => (
                <Table.Tr key={it.id}>
                  <Table.Td>
                    <Text size="sm">{it.description}</Text>
                    <Text size="xs" c="dimmed">{it.feeType.replace(/_/g, ' ')} · {it.chargeableDays ?? 0} day(s) @ {fmt(it.unitRate, it.currency)}</Text>
                  </Table.Td>
                  <Table.Td ta="right"><Text fw={600}>{fmt(it.amount, it.currency)}</Text></Table.Td>
                </Table.Tr>
              ))}
            </Table.Tbody>
          </Table>

          <Divider />
          <Group justify="space-between"><Text size="sm" c="dimmed">Subtotal</Text><Text>{fmt(inv.subtotalAmount, inv.currency)}</Text></Group>
          <Group justify="space-between"><Text size="sm" c="dimmed">Tax</Text><Text>{fmt(inv.taxAmount, inv.currency)}</Text></Group>
          <Group justify="space-between"><Text fw={700}>Total</Text><Text fw={700}>{fmt(inv.totalAmount, inv.currency)}</Text></Group>
          <Group justify="space-between"><Text size="sm" c="dimmed">Paid</Text><Text>{fmt(inv.paidAmount, inv.currency)}</Text></Group>
          <Group justify="space-between"><Text fw={600}>Balance</Text><Text fw={600}>{fmt(inv.balanceAmount, inv.currency)}</Text></Group>

          {(inv.payments ?? []).length > 0 && (
            <>
              <Divider label="Payment history" labelPosition="left" />
              {(inv.payments ?? []).map((p, i) => (
                <Group key={i} justify="space-between">
                  <Text size="xs" c="dimmed">{fmtDate(p.paidAt)} · {p.method ?? '—'}{p.reference ? ` · ${p.reference}` : ''}</Text>
                  <Text size="sm">{fmt(p.amount, inv.currency)}</Text>
                </Group>
              ))}
            </>
          )}

          {canPay && (
            <>
              <Divider label="Record payment" labelPosition="left" />
              <Group align="flex-end">
                <NumberInput
                  label="Amount"
                  min={0}
                  value={payAmount}
                  onChange={(v) => setPayAmount(v === '' ? '' : Number(v))}
                  style={{ flex: 1 }}
                />
                <Button leftSection={<CreditCard size={16} />} loading={pay.isPending} onClick={handlePay}>
                  Pay
                </Button>
              </Group>
            </>
          )}

          <Group justify="flex-end" mt="sm">
            {inv.status !== 'PAID' && inv.status !== 'CANCELLED' && (
              <Button variant="light" color="red" leftSection={<Ban size={16} />} loading={cancel.isPending} onClick={handleCancel}>
                Cancel invoice
              </Button>
            )}
          </Group>
        </Stack>
      )}
    </Modal>
  );
}
