import type {
  ImportUnloadedItem,
  WarehouseFeeInvoice,
  WarehouseInventoryItem,
} from '@/types/warehouse';
import type { BookingDetail } from '@/types/booking';

type PdfLine = {
  text: string;
  size?: number;
  bold?: boolean;
  x?: number;
  yGap?: number;
  color?: 'black' | 'green';
  align?: 'left' | 'center' | 'right';
};

export interface WarehouseExitPaperContext {
  invoice: WarehouseFeeInvoice;
  releasedItem?: WarehouseInventoryItem;
  inventory?: WarehouseInventoryItem;
  booking?: BookingDetail | null;
  releasedAt?: Date;
}

export interface WarehouseHandoverPdfContext {
  item: ImportUnloadedItem | WarehouseInventoryItem;
  handedOverAt?: Date;
}

const escapePdfText = (value: string) =>
  value.replace(/\\/g, '\\\\').replace(/\(/g, '\\(').replace(/\)/g, '\\)');

const fmtDate = (value: unknown) => {
  if (!value) return '-';
  const date = new Date(value as string | Date);
  return Number.isNaN(date.getTime()) ? '-' : date.toLocaleString();
};

const GREEN = '0 0.55 0.32';

const circlePath = (cx: number, cy: number, r: number) => {
  const k = 0.5522847498;
  const c = r * k;
  return [
    `${cx + r} ${cy} m`,
    `${cx + r} ${cy + c} ${cx + c} ${cy + r} ${cx} ${cy + r} c`,
    `${cx - c} ${cy + r} ${cx - r} ${cy + c} ${cx - r} ${cy} c`,
    `${cx - r} ${cy - c} ${cx - c} ${cy - r} ${cx} ${cy - r} c`,
    `${cx + c} ${cy - r} ${cx + r} ${cy - c} ${cx + r} ${cy} c`,
    'h',
  ].join('\n');
};

const stampText = (text: string, x: number, y: number, size: number, bold = false) =>
  `BT\n${GREEN} rg\n/${bold ? 'F2' : 'F1'} ${size} Tf\n${x} ${y} Td\n(${escapePdfText(text)}) Tj\nET`;

const buildCircularSeal = (cx: number, cy: number, label: 'PAID' | 'CLEARED') =>
  [
    'q',
    `${GREEN} RG`,
    `${GREEN} rg`,
    '2.2 w',
    circlePath(cx, cy, 52),
    'S',
    '0.9 w',
    circlePath(cx, cy, 42),
    'S',
    stampText('EDR FREIGHT', cx - 33, cy + 24, 9, true),
    stampText(label, cx - (label === 'CLEARED' ? 36 : 21), cy - 4, label === 'CLEARED' ? 17 : 20, true),
    stampText(label === 'CLEARED' ? 'GATE RELEASE' : 'WAREHOUSE', cx - (label === 'CLEARED' ? 34 : 32), cy - 25, 8),
    'Q',
  ].join('\n');

const estimateTextWidth = (text: string, size: number) => text.length * size * 0.52;

const textX = (text: string, size: number, align: PdfLine['align'] = 'left', x?: number) => {
  if (typeof x === 'number') return x;
  if (align === 'center') return Math.max(36, (595 - estimateTextWidth(text, size)) / 2);
  if (align === 'right') return Math.max(36, 535 - estimateTextWidth(text, size));
  return 60;
};

const lineOp = (x1: number, y1: number, x2: number, y2: number, color = '0.65 0.7 0.76') =>
  `q\n${color} RG\n0.8 w\n${x1} ${y1} m\n${x2} ${y2} l\nS\nQ`;

const textOp = (
  text: string,
  x: number,
  y: number,
  size = 10,
  bold = false,
  color = '0 0 0',
) => `BT\n${color} rg\n/${bold ? 'F2' : 'F1'} ${size} Tf\n${x} ${y} Td\n(${escapePdfText(text)}) Tj\nET`;

const buildWarehouseOfficerSealBand = () => [
  lineOp(60, 218, 535, 218),
  textOp('WAREHOUSE OFFICER SEAL', 92, 194, 9, true, GREEN),
  buildCircularSeal(170, 128, 'CLEARED'),
  textOp('Officer in charge name / signature / date:', 292, 154, 10),
  lineOp(292, 132, 535, 132, '0 0 0'),
  textOp('Customer or driver name / signature / date:', 292, 94, 10),
  lineOp(292, 72, 535, 72, '0 0 0'),
];

function buildSimplePdf(lines: PdfLine[], rawOps: string[] = []): Blob {
  let y = 800;
  const streamLines = lines.map((line) => {
    y -= line.yGap ?? 16;
    const size = line.size ?? 10;
    const font = line.bold ? '/F2' : '/F1';
    const color = line.color === 'green' ? `${GREEN} rg` : '0 0 0 rg';
    return `BT\n${color}\n${font} ${size} Tf\n${textX(line.text, size, line.align, line.x)} ${y} Td\n(${escapePdfText(line.text)}) Tj\nET`;
  });
  const stream = [...rawOps, ...streamLines].join('\n');
  const objects = [
    '<< /Type /Catalog /Pages 2 0 R >>',
    '<< /Type /Pages /Kids [3 0 R] /Count 1 >>',
    '<< /Type /Page /Parent 2 0 R /MediaBox [0 0 595 842] /Resources << /Font << /F1 4 0 R /F2 5 0 R >> >> /Contents 6 0 R >>',
    '<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>',
    '<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica-Bold >>',
    `<< /Length ${stream.length} >>\nstream\n${stream}\nendstream`,
  ];

  let pdf = '%PDF-1.4\n';
  const offsets = [0];
  objects.forEach((object, index) => {
    offsets.push(pdf.length);
    pdf += `${index + 1} 0 obj\n${object}\nendobj\n`;
  });
  const xref = pdf.length;
  pdf += `xref\n0 ${objects.length + 1}\n0000000000 65535 f \n`;
  offsets.slice(1).forEach((offset) => {
    pdf += `${String(offset).padStart(10, '0')} 00000 n \n`;
  });
  pdf += `trailer\n<< /Size ${objects.length + 1} /Root 1 0 R >>\nstartxref\n${xref}\n%%EOF\n`;
  return new Blob([pdf], { type: 'application/pdf' });
}

const firstText = (...values: Array<unknown>) => {
  for (const value of values) {
    if (value !== null && value !== undefined && String(value).trim()) return String(value);
  }
  return '-';
};

const tons = (value: unknown) => {
  const num = Number(value ?? 0);
  if (!Number.isFinite(num) || num <= 0) return null;
  return `${num.toLocaleString(undefined, { maximumFractionDigits: 3 })} ton`;
};

const containerSummary = (booking?: BookingDetail | null, inventory?: WarehouseInventoryItem) => {
  const explicitNumber = (inventory as unknown as { containerNumber?: string | null })?.containerNumber;
  if (explicitNumber) return explicitNumber;
  const containers = booking?.bookingContainers ?? [];
  if (!containers.length) return '-';
  return containers
    .map((item) => {
      const type = item.containerType?.code ?? item.containerType?.label ?? item.containerTypeId;
      return `${item.quantity} x ${type}`;
    })
    .join(', ');
};

const shortId = (value: unknown) => {
  const text = firstText(value);
  return text === '-' ? '-' : text.slice(0, 8);
};

const compactWeight = (value: unknown) => {
  const num = Number(value ?? 0);
  if (!Number.isFinite(num) || num <= 0) return '-';
  return num.toLocaleString(undefined, { maximumFractionDigits: 3 });
};

const handoverValue = (item: ImportUnloadedItem | WarehouseInventoryItem, key: string) =>
  (item as unknown as Record<string, unknown>)[key];

const handoverBookingValue = (item: ImportUnloadedItem | WarehouseInventoryItem, key: string) =>
  ((item as WarehouseInventoryItem).booking as unknown as Record<string, unknown> | null | undefined)?.[key];

export function buildWarehouseHandoverPdf({ item, handedOverAt = new Date() }: WarehouseHandoverPdfContext) {
  const bookingReference = firstText(
    handoverValue(item, 'bookingReference'),
    handoverBookingValue(item, 'reference'),
    item.bookingId,
  );
  const customerName = firstText(
    handoverValue(item, 'customerName'),
    handoverBookingValue(item, 'customerName'),
    handoverBookingValue(item, 'companyName'),
  );
  const containerNumber = firstText(handoverValue(item, 'containerNumber'));
  const cargoType = firstText(handoverValue(item, 'cargoType'), handoverValue(item, 'cargoDescription'));
  const currentStatus = firstText(handoverValue(item, 'currentStatus'), (item as WarehouseInventoryItem).status);
  const handoverReference = `HND-${bookingReference.replace(/[^a-zA-Z0-9]+/g, '-')}`;
  const goodsSummary = firstText(containerNumber, cargoType, (item as WarehouseInventoryItem).goodsId);

  return buildSimplePdf([
    { text: 'Ethio-Djibouti Railway S.C.', size: 12, bold: true, yGap: 0, align: 'center' },
    { text: 'Import Goods Handover Document', size: 23, bold: true, yGap: 28, align: 'center' },
    { text: '[ EDR TO CUSTOMER ]', size: 14, bold: true, color: 'green', yGap: 24, align: 'center' },
    { text: `Document No: ${handoverReference}`, bold: true, yGap: 30, align: 'center' },
    { text: `Handover Date & Time: ${fmtDate(handedOverAt)}`, align: 'center' },
    { text: `From: Ethio-Djibouti Railway S.C.`, align: 'center' },
    { text: `To Customer: ${customerName}`, align: 'center' },
    { text: `Customer ID: ${shortId(handoverValue(item, 'customerId'))}`, align: 'center' },
    { text: `Booking Reference: ${bookingReference}`, align: 'center' },
    { text: `Booking ID: ${shortId(item.bookingId)}`, align: 'center' },
    { text: `Train Schedule: ${firstText(handoverValue(item, 'trainSchedule'))}`, align: 'center' },
    { text: `Arrival Time: ${fmtDate(handoverValue(item, 'arrivalTime') ?? (item as WarehouseInventoryItem).arrivedAt)}`, align: 'center' },
    { text: `Release Order: ${firstText((item as WarehouseInventoryItem).releaseOrderReference)}`, align: 'center' },
    { text: `Release Date: ${fmtDate((item as WarehouseInventoryItem).releaseDate)}`, align: 'center' },
    { text: 'GOODS LIST', size: 13, bold: true, yGap: 30, align: 'center' },
    { text: `1. ${goodsSummary}`, bold: true, align: 'center' },
    { text: `Container: ${containerNumber}     Cargo: ${cargoType}`, align: 'center' },
    { text: `Weight: ${compactWeight(item.weight)}     Status: ${currentStatus}`, align: 'center' },
    { text: `Inspection: ${firstText(item.inspectionStatus)}     Pickup Option: ${firstText(handoverValue(item, 'pickupOption'), 'TERMINAL_PICKUP')}`, align: 'center' },
    { text: `Warehouse: ${firstText((item as WarehouseInventoryItem).warehouse?.name, (item as WarehouseInventoryItem).warehouse?.code)}     Yard: ${firstText((item as WarehouseInventoryItem).yard?.name, (item as WarehouseInventoryItem).yard?.code)}`, align: 'center' },
    { text: 'This document confirms EDR handed over the listed import goods to the customer after warehouse inspection.', yGap: 30, align: 'center' },
  ], [
    ...buildWarehouseOfficerSealBand(),
  ]);
}

export function buildWarehouseExitPaperPdf(input: WarehouseFeeInvoice | WarehouseExitPaperContext, releasedItemArg?: WarehouseInventoryItem) {
  const context: WarehouseExitPaperContext =
    'invoice' in input ? input : { invoice: input, releasedItem: releasedItemArg };
  const { invoice, booking } = context;
  const releasedItem = context.releasedItem;
  const inventory = context.inventory ?? releasedItem;
  const releasedAt = context.releasedAt ?? new Date();
  const releaseReference = firstText(
    inventory?.releaseOrderReference,
    releasedItem?.releaseOrderReference,
    invoice.inventoryReference,
    booking?.reference ? `REL-${booking.reference.replace(/^BK-?/i, '')}` : null,
  );
  const customerName = firstText(
    booking?.company?.name,
    booking?.company?.companyName,
    booking?.company?.label,
    booking?.company?.contactPersonName,
    invoice.customerName,
  );
  const weightTons = firstText(tons(booking?.cargoTotalWeightVgm), tons(inventory?.weight));
  const inventoryInfo = firstText(
    invoice.inventoryInfo,
    invoice.containerNumber,
    invoice.cargoDescription,
    inventory?.status,
    releasedItem?.status,
  );
  const bookingReference = firstText(
    booking?.reference,
    (inventory as unknown as { bookingReference?: string })?.bookingReference,
    invoice.bookingReference,
    releasedItem?.booking?.reference,
  );

  return buildSimplePdf([
    { text: 'Ethio-Djibouti Railway S.C.', size: 12, bold: true, yGap: 0, align: 'center' },
    { text: 'Warehouse Release / Exit Paper', size: 23, bold: true, yGap: 28, align: 'center' },
    { text: '[ GATE CLEARANCE ]', size: 14, bold: true, color: 'green', yGap: 24, align: 'center' },
    { text: `Release Reference: ${releaseReference}`, bold: true, yGap: 30, align: 'center' },
    { text: `Invoice No: ${invoice.invoiceNumber}`, align: 'center' },
    { text: `Booking Reference: ${bookingReference}`, align: 'center' },
    { text: `Customer: ${customerName}`, align: 'center' },
    { text: `Inventory Info: ${inventoryInfo}`, align: 'center' },
    { text: `Warehouse: ${firstText(inventory?.warehouse?.name, inventory?.warehouse?.code)}`, align: 'center' },
    { text: `Yard: ${firstText(inventory?.yard?.name, inventory?.yard?.code)}`, align: 'center' },
    { text: `Zone: ${firstText(inventory?.zone?.name, inventory?.zone?.code)}`, align: 'center' },
    { text: `Booking Container: ${containerSummary(booking, inventory)}`, align: 'center' },
    { text: `Weight: ${weightTons}`, align: 'center' },
    { text: `Inventory Status: ${releasedItem?.status ?? inventory?.status ?? 'RELEASED'}`, align: 'center' },
    { text: `Clearance: ${invoice.clearanceStatus ?? 'CLEARED FOR WAREHOUSE EXIT'}`, bold: true, color: 'green', align: 'center' },
    { text: `Release Date & Time: ${fmtDate(releasedAt)}`, align: 'center' },
    { text: 'This sealed document authorizes the listed booking/goods to leave the warehouse gate.', yGap: 30, align: 'center' },
  ], [
    ...buildWarehouseOfficerSealBand(),
  ]);
}
