import { useMemo, useState } from 'react';
import {
  Badge,
  Button,
  Card,
  Group,
  Loader,
  Modal,
  SimpleGrid,
  Stack,
  Table,
  Text,
  TextInput,
} from '@mantine/core';
import { CheckCircle2, Download, Eye, FileText, Printer, Search } from 'lucide-react';
import type { ReactNode } from 'react';

import { DataTable, type ColumnDef } from '@edr/ui-common';
import ListControls from '@/components/common/ListControls';
import { useListControls } from '@/hooks/useListControls';

import { PageContainer, PageHeader } from '@/components/page';
import { VisualEmptyState, formatDate, formatNumber } from '@/components/warehouses';
import {
  useAcknowledgeInterchangeDocument,
  useDisputeInterchangeDocument,
  useInterchangeDocument,
  useInterchangeDocuments,
} from '@/hooks/useInterchangeDocuments';
import { useToast } from '@/hooks/use-toast';
import { interchangeDocumentsService } from '@/services/interchange-documents.service';
import type { InterchangeDocument, InterchangeDocumentStatus } from '@/types/interchangeDocument';

const statusColor: Record<InterchangeDocumentStatus, string> = {
  DRAFT: 'gray',
  GENERATED: 'blue',
  ACKNOWLEDGED: 'green',
  DISPUTED: 'red',
  CANCELLED: 'gray',
};

const getErrorMessage = (error: unknown) => {
  if (error && typeof error === 'object' && 'response' in error) {
    const response = (error as { response?: { data?: { message?: unknown } } }).response;
    const message = response?.data?.message;
    if (Array.isArray(message)) return message.join(', ');
    if (typeof message === 'string') return message;
  }
  return error instanceof Error ? error.message : undefined;
};

const escapeHtml = (value: unknown) =>
  String(value ?? '-')
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;');

const filenameFor = (document: InterchangeDocument) =>
  `${document.documentNo || document.id}-interchange-document.html`.replace(/[\\/:*?"<>|]/g, '-');

const buildPrintableInterchangeHtml = (document: InterchangeDocument) => {
  const items = document.items ?? [];
  const rows = items
    .map(
      (item, index) => `
        <tr>
          <td>${index + 1}</td>
          <td>${escapeHtml(item.bookingReference)}</td>
          <td>${escapeHtml(item.itemType)}</td>
          <td>${escapeHtml(item.containerNumber)}</td>
          <td>${escapeHtml(item.sealNumber)}</td>
          <td>${escapeHtml(item.cargoType ?? item.cargoDescription)}</td>
          <td>${escapeHtml(formatNumber(item.weight))}</td>
          <td>${escapeHtml(formatNumber(item.quantity))}</td>
          <td>${escapeHtml(item.wagonNumber)}</td>
          <td>${escapeHtml(item.conditionStatus)}</td>
          <td>${escapeHtml(item.damageDescription)}</td>
        </tr>`,
    )
    .join('');

  return `<!doctype html>
<html>
<head>
  <meta charset="utf-8" />
  <title>${escapeHtml(document.documentNo)} Interchange Document</title>
  <style>
    @page { size: A4 landscape; margin: 14mm; }
    * { box-sizing: border-box; }
    body { font-family: Arial, sans-serif; color: #111827; margin: 0; }
    .top { display: flex; justify-content: space-between; gap: 24px; border-bottom: 2px solid #111827; padding-bottom: 14px; }
    h1 { margin: 0; font-size: 24px; }
    .muted { color: #4b5563; font-size: 12px; }
    .stamp { border: 2px solid #15803d; color: #15803d; border-radius: 999px; padding: 14px 18px; text-align: center; font-weight: 700; }
    .grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px 18px; margin: 18px 0; }
    .field { border-bottom: 1px solid #d1d5db; padding-bottom: 6px; }
    .label { color: #6b7280; font-size: 10px; text-transform: uppercase; letter-spacing: .04em; }
    .value { font-size: 13px; font-weight: 700; margin-top: 3px; }
    table { width: 100%; border-collapse: collapse; margin-top: 12px; font-size: 11px; }
    th, td { border: 1px solid #d1d5db; padding: 6px; text-align: left; vertical-align: top; }
    th { background: #f3f4f6; }
    .signatures { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; margin-top: 34px; }
    .signature { border-top: 1px solid #111827; padding-top: 8px; min-height: 48px; }
    .footer { margin-top: 16px; font-size: 10px; color: #6b7280; }
  </style>
</head>
<body>
  <div class="top">
    <div>
      <h1>EDR / Djibouti Port Interchange Document</h1>
      <div class="muted">Official export handover document</div>
      <div class="muted">Document No: ${escapeHtml(document.documentNo)}</div>
    </div>
    <div class="stamp">${escapeHtml(document.status)}<br/>SIGNED HANDOVER</div>
  </div>

  <div class="grid">
    <div class="field"><div class="label">Direction</div><div class="value">${escapeHtml(document.direction)}</div></div>
    <div class="field"><div class="label">Train No</div><div class="value">${escapeHtml(document.trainNo)}</div></div>
    <div class="field"><div class="label">Handover Location</div><div class="value">${escapeHtml(document.handoverLocation)}</div></div>
    <div class="field"><div class="label">Handover From</div><div class="value">${escapeHtml(document.handoverFrom)}</div></div>
    <div class="field"><div class="label">Handover To</div><div class="value">${escapeHtml(document.handoverTo)}</div></div>
    <div class="field"><div class="label">Generated At</div><div class="value">${escapeHtml(formatDate(document.generatedAt))}</div></div>
    <div class="field"><div class="label">Acknowledged At</div><div class="value">${escapeHtml(formatDate(document.acknowledgedAt))}</div></div>
    <div class="field"><div class="label">Signed by EDR</div><div class="value">${escapeHtml(document.generatedBy)}</div></div>
    <div class="field"><div class="label">Signed by Djibouti Port</div><div class="value">${escapeHtml(document.acknowledgedBy)}</div></div>
    <div class="field"><div class="label">Port Operator</div><div class="value">${escapeHtml(document.portOperatorName)}</div></div>
    <div class="field"><div class="label">Manifest Ref</div><div class="value">${escapeHtml(document.manifestReference)}</div></div>
  </div>

  <table>
    <thead>
      <tr>
        <th>#</th>
        <th>Booking</th>
        <th>Type</th>
        <th>Container</th>
        <th>Seal</th>
        <th>Cargo</th>
        <th>Weight</th>
        <th>Qty</th>
        <th>Wagon</th>
        <th>Condition</th>
        <th>Damage / Notes</th>
      </tr>
    </thead>
    <tbody>${rows || '<tr><td colspan="11">No items</td></tr>'}</tbody>
  </table>

  <div class="signatures">
    <div class="signature">EDR Representative: ${escapeHtml(document.generatedBy)}</div>
    <div class="signature">Djibouti Port Operator: ${escapeHtml(document.acknowledgedBy)}</div>
  </div>
  <div class="footer">Generated from EDR Freight Management System. Printed on ${escapeHtml(new Date().toLocaleString())}.</div>
</body>
</html>`;
};

function DetailField({ label, value }: { label: string; value: ReactNode }) {
  return (
    <Stack gap={2}>
      <Text size="xs" c="dimmed">
        {label}
      </Text>
      <Text size="sm" fw={600}>
        {value || '-'}
      </Text>
    </Stack>
  );
}

function InterchangeDocumentDetail({ id }: { id: string }) {
  const { data: document, isLoading } = useInterchangeDocument(id);

  if (isLoading) {
    return (
      <Group justify="center" py="xl">
        <Loader />
      </Group>
    );
  }

  if (!document) return null;

  const items = document.items ?? [];

  return (
    <Stack gap="lg">
      <SimpleGrid cols={{ base: 1, sm: 2, lg: 4 }}>
        <DetailField label="Document No" value={document.documentNo} />
        <DetailField label="Direction" value={document.direction} />
        <DetailField label="Train No" value={document.trainNo} />
        <DetailField label="Handover Location" value={document.handoverLocation} />
        <DetailField label="Handover From" value={document.handoverFrom} />
        <DetailField label="Handover To" value={document.handoverTo} />
        <DetailField
          label="Status"
          value={
            <Badge variant="light" color={statusColor[document.status]}>
              {document.status}
            </Badge>
          }
        />
        <DetailField label="Generated At" value={formatDate(document.generatedAt)} />
        <DetailField label="Acknowledged At" value={formatDate(document.acknowledgedAt)} />
        <DetailField label="Signed by EDR" value={document.generatedBy} />
        <DetailField label="Signed by Djibouti Port" value={document.acknowledgedBy} />
        <DetailField label="Customs Ref" value={document.customsReference} />
        <DetailField label="Manifest Ref" value={document.manifestReference} />
      </SimpleGrid>

      <Table.ScrollContainer minWidth={980}>
        <Table striped highlightOnHover verticalSpacing="sm">
          <Table.Thead>
            <Table.Tr>
              <Table.Th>Booking Reference</Table.Th>
              <Table.Th>Item Type</Table.Th>
              <Table.Th>Container Number</Table.Th>
              <Table.Th>Seal Number</Table.Th>
              <Table.Th>Cargo Type</Table.Th>
              <Table.Th>Weight</Table.Th>
              <Table.Th>Quantity</Table.Th>
              <Table.Th>Wagon Number</Table.Th>
              <Table.Th>Condition</Table.Th>
              <Table.Th>Damage Description</Table.Th>
              <Table.Th>Remarks</Table.Th>
            </Table.Tr>
          </Table.Thead>
          <Table.Tbody>
            {items.map((item) => (
              <Table.Tr key={item.id}>
                <Table.Td>{item.bookingReference ?? '-'}</Table.Td>
                <Table.Td>{item.itemType}</Table.Td>
                <Table.Td>{item.containerNumber ?? '-'}</Table.Td>
                <Table.Td>{item.sealNumber ?? '-'}</Table.Td>
                <Table.Td>{item.cargoType ?? item.cargoDescription ?? '-'}</Table.Td>
                <Table.Td>{formatNumber(item.weight)}</Table.Td>
                <Table.Td>{formatNumber(item.quantity)}</Table.Td>
                <Table.Td>{item.wagonNumber ?? '-'}</Table.Td>
                <Table.Td>
                  <Badge
                    variant="light"
                    color={item.conditionStatus === 'GOOD' ? 'green' : item.conditionStatus === 'UNKNOWN' ? 'gray' : 'orange'}
                    size="sm"
                  >
                    {item.conditionStatus}
                  </Badge>
                </Table.Td>
                <Table.Td>{item.damageDescription ?? '-'}</Table.Td>
                <Table.Td>{item.remarks ?? '-'}</Table.Td>
              </Table.Tr>
            ))}
          </Table.Tbody>
        </Table>
      </Table.ScrollContainer>
    </Stack>
  );
}

export default function InterchangeDocumentsPage() {
  const { toast } = useToast();
  const [search, setSearch] = useState('');
  const [viewId, setViewId] = useState<string | null>(null);
  const filter = useMemo(() => ({ search: search.trim() || undefined }), [search]);
  const { data: documents = [], isLoading } = useInterchangeDocuments(filter);
  // Search stays server-side (passed in `filter`); this adds the date range and
  // pagination over what comes back.
  const controls = useListControls(documents, { dateKey: 'generatedAt' });
  const acknowledge = useAcknowledgeInterchangeDocument();
  const dispute = useDisputeInterchangeDocument();

  const getPrintableDocument = async (interchangeDocument: InterchangeDocument) => {
    if (interchangeDocument.items?.length) return interchangeDocument;
    return interchangeDocumentsService.getById(interchangeDocument.id).then((response) => response.data);
  };

  const printDocument = async (interchangeDocument: InterchangeDocument) => {
    const fullDocument = await getPrintableDocument(interchangeDocument);
    const win = window.open('', '_blank');
    if (!win) {
      toast({ variant: 'destructive', title: 'Pop-up blocked', description: 'Allow pop-ups to print the document.' });
      return;
    }
    win.document.write(buildPrintableInterchangeHtml(fullDocument));
    win.document.close();
    win.focus();
    setTimeout(() => win.print(), 250);
  };

  const downloadDocument = async (interchangeDocument: InterchangeDocument) => {
    const fullDocument = await getPrintableDocument(interchangeDocument);
    const blob = new Blob([buildPrintableInterchangeHtml(fullDocument)], { type: 'text/html;charset=utf-8' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = filenameFor(fullDocument);
    document.body.appendChild(a);
    a.click();
    a.remove();
    URL.revokeObjectURL(url);
  };

  const run = async (fn: () => Promise<unknown>, title: string) => {
    try {
      await fn();
      toast({ title });
    } catch (error) {
      toast({ variant: 'destructive', title: 'Action failed', description: getErrorMessage(error) });
    }
  };

  const acknowledgeDocument = (document: InterchangeDocument) => {
    const acknowledgedBy = window.prompt('Acknowledged by');
    if (!acknowledgedBy) return;
    run(async () => {
      const response = await acknowledge.mutateAsync({ id: document.id, acknowledgedBy });
      await printDocument(response.data);
    }, 'Interchange document acknowledged');
  };

  const disputeDocument = (document: InterchangeDocument) => {
    const remarks = window.prompt('Dispute reason');
    if (!remarks) return;
    run(() => dispute.mutateAsync({ id: document.id, remarks }), 'Interchange document disputed');
  };

  const documentColumns: ColumnDef<InterchangeDocument>[] = [
    {
      id: 'documentNo',
      header: 'Document No',
      cell: ({ row }) => (
        <Text fw={700} size="sm">
          {row.original.documentNo}
        </Text>
      ),
    },
    { id: 'direction', header: 'Direction', cell: ({ row }) => row.original.direction },
    { id: 'train', header: 'Train No', cell: ({ row }) => row.original.trainNo ?? '-' },
    { id: 'handoverLocation', header: 'Handover Location', cell: ({ row }) => row.original.handoverLocation },
    { id: 'handoverFrom', header: 'Handover From', cell: ({ row }) => row.original.handoverFrom },
    { id: 'handoverTo', header: 'Handover To', cell: ({ row }) => row.original.handoverTo },
    {
      id: 'status',
      header: 'Status',
      cell: ({ row }) => (
        <Badge variant="light" color={statusColor[row.original.status]}>
          {row.original.status}
        </Badge>
      ),
    },
    {
      id: 'signedBy',
      header: 'Signed By',
      cell: ({ row }) => (
        <Stack gap={0}>
          <Text size="sm">{row.original.generatedBy ?? '-'}</Text>
          <Text size="xs" c="dimmed">
            {row.original.acknowledgedBy ?? 'Awaiting Djibouti Port'}
          </Text>
        </Stack>
      ),
    },
    { id: 'generatedAt', header: 'Generated At', cell: ({ row }) => formatDate(row.original.generatedAt) },
    {
      id: 'actions',
      header: '',
      meta: { headerClassName: 'text-right', cellClassName: 'text-right' },
      cell: ({ row }) => {
        const doc = row.original;
        return (
          <Group gap="xs" justify="flex-end" wrap="nowrap">
            <Button
              size="compact-xs"
              variant="light"
              leftSection={<Eye size={14} />}
              onClick={() => setViewId(doc.id)}
            >
              View
            </Button>
            {doc.status === 'GENERATED' ? (
              <Button
                size="compact-xs"
                color="green"
                variant="light"
                leftSection={<CheckCircle2 size={14} />}
                onClick={() => acknowledgeDocument(doc)}
              >
                Acknowledge
              </Button>
            ) : null}
            {doc.status === 'ACKNOWLEDGED' ? (
              <>
                <Button
                  size="compact-xs"
                  color="blue"
                  variant="light"
                  leftSection={<Printer size={14} />}
                  onClick={() => run(() => printDocument(doc), 'Print view opened')}
                >
                  Print
                </Button>
                <Button
                  size="compact-xs"
                  color="blue"
                  variant="light"
                  leftSection={<Download size={14} />}
                  onClick={() => run(() => downloadDocument(doc), 'Document downloaded')}
                >
                  Download
                </Button>
              </>
            ) : null}
            {/* Disputes are raised BEFORE acknowledgement; a registered dispute
                (DISPUTED) is read-only — its row offers View only. */}
            {doc.status === 'GENERATED' ? (
              <Button
                size="compact-xs"
                color="orange"
                variant="light"
                leftSection={<FileText size={14} />}
                onClick={() => disputeDocument(doc)}
              >
                Dispute
              </Button>
            ) : null}
          </Group>
        );
      },
    },
  ];

  return (
    <PageContainer>
      <PageHeader
        title="Interchange Documents"
        subtitle="Official freight handover documents with booking, container and cargo line items."
      />

      <Card withBorder radius="md" padding="lg">
        <Group justify="space-between" mb="md">
          <Text fw={600}>{controls.totalCount} document(s)</Text>
          <TextInput
            w={{ base: '100%', sm: 320 }}
            leftSection={<Search size={16} />}
            placeholder="Search documents"
            value={search}
            onChange={(event) => setSearch(event.currentTarget.value)}
          />
        </Group>

        <ListControls
          showSearch={false}
          search=""
          onSearchChange={() => {}}
          dateFrom={controls.dateFrom}
          onDateFromChange={controls.setDateFrom}
          dateTo={controls.dateTo}
          onDateToChange={controls.setDateTo}
          dateLabel="Generated"
          hasFilters={controls.hasFilters}
          onReset={controls.reset}
        />

        {!isLoading && documents.length === 0 ? (
          <VisualEmptyState
            variant="container"
            title="No interchange documents"
            description="Generated freight handover documents appear here."
          />
        ) : (
          <DataTable
            columns={documentColumns}
            data={controls.pagedRows}
            status={isLoading ? 'loading' : 'success'}
            containerClassName="border-0 shadow-none"
            {...controls.tableProps}
          />
        )}
      </Card>

      <Modal opened={Boolean(viewId)} onClose={() => setViewId(null)} title="Interchange Document" size="90%">
        {viewId ? <InterchangeDocumentDetail id={viewId} /> : null}
      </Modal>
    </PageContainer>
  );
}
