import React from 'react'
import { renderToBuffer, Document, Page, Text, View, StyleSheet } from '@react-pdf/renderer'

interface InvoiceData {
  invoiceNumber: string
  issueDate: string
  dueDate: string | null
  company: {
    name: string
    email: string
    phone?: string | null
    address?: any
  }
  subscription?: {
    plan: string
    billingPeriod: string
    currentPeriodStart?: string | null
    currentPeriodEnd?: string | null
    currency: string
  }
  amount: number
  currency: string
  status: string
  paymentProvider: string
  transactionId?: string | null
  paidAt?: string | null
  lineItems?: Array<{
    description: string
    amount: number
    currency: string
    quantity?: number
    unitAmount?: number
    periodStart?: string | null
    periodEnd?: string | null
  }>
  totals?: {
    subtotalAmount: number
    discountAmount: number
    creditAmount: number
    taxAmount: number
    totalAmount: number
    amountPaid: number
    amountDue: number
  }
}

const PLAN_LABEL: Record<string, string> = {
  STARTER: 'Starter',
  GROWTH: 'Growth',
  PRO: 'Pro',
}

const PERIOD_LABEL: Record<string, string> = {
  MONTHLY: 'Monthly',
  ANNUAL: 'Annual',
}

const STATUS_COLORS: Record<string, string> = {
  PAID: '#10b981',
  PENDING: '#f59e0b',
  OPEN: '#f59e0b',
  PAYMENT_PENDING: '#f59e0b',
  PARTIALLY_PAID: '#f59e0b',
  PAST_DUE: '#ef4444',
  FAILED: '#ef4444',
  REFUNDED: '#6b7280',
  PARTIALLY_REFUNDED: '#6b7280',
  VOID: '#6b7280',
  UNCOLLECTIBLE: '#6b7280',
}

const colors = {
  bg: '#0f0f11',
  surface: '#18181b',
  border: '#27272a',
  textPrimary: '#f4f4f5',
  textSecondary: '#a1a1aa',
  textMuted: '#71717a',
  accent: '#10b981',
  white: '#ffffff',
}

const s = StyleSheet.create({
  page: {
    backgroundColor: colors.bg,
    paddingHorizontal: 48,
    paddingVertical: 48,
    fontFamily: 'Helvetica',
    color: colors.textPrimary,
  },
  header: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'flex-start',
    marginBottom: 40,
    paddingBottom: 24,
    borderBottomWidth: 1,
    borderBottomColor: colors.border,
  },
  brandName: {
    fontSize: 22,
    fontFamily: 'Helvetica-Bold',
    color: colors.accent,
    letterSpacing: 0.5,
  },
  brandTagline: {
    fontSize: 9,
    color: colors.textMuted,
    marginTop: 3,
  },
  invoiceMeta: {
    alignItems: 'flex-end',
  },
  invoiceTitle: {
    fontSize: 26,
    fontFamily: 'Helvetica-Bold',
    color: colors.white,
    letterSpacing: 1,
  },
  invoiceNumber: {
    fontSize: 11,
    color: colors.textSecondary,
    marginTop: 4,
  },
  section: {
    marginBottom: 24,
  },
  sectionLabel: {
    fontSize: 8,
    fontFamily: 'Helvetica-Bold',
    color: colors.textMuted,
    letterSpacing: 1.2,
    textTransform: 'uppercase',
    marginBottom: 8,
  },
  row: {
    flexDirection: 'row',
    gap: 24,
    marginBottom: 24,
  },
  col: {
    flex: 1,
    backgroundColor: colors.surface,
    borderRadius: 8,
    padding: 16,
    borderWidth: 1,
    borderColor: colors.border,
  },
  colLabel: {
    fontSize: 8,
    fontFamily: 'Helvetica-Bold',
    color: colors.textMuted,
    letterSpacing: 1,
    textTransform: 'uppercase',
    marginBottom: 10,
  },
  companyName: {
    fontSize: 13,
    fontFamily: 'Helvetica-Bold',
    color: colors.textPrimary,
    marginBottom: 4,
  },
  companyDetail: {
    fontSize: 10,
    color: colors.textSecondary,
    marginBottom: 2,
  },
  metaRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    marginBottom: 6,
  },
  metaKey: {
    fontSize: 9,
    color: colors.textMuted,
  },
  metaValue: {
    fontSize: 9,
    color: colors.textSecondary,
    fontFamily: 'Helvetica-Bold',
  },
  table: {
    backgroundColor: colors.surface,
    borderRadius: 8,
    borderWidth: 1,
    borderColor: colors.border,
    overflow: 'hidden',
    marginBottom: 20,
  },
  tableHeader: {
    flexDirection: 'row',
    backgroundColor: '#1c1c1f',
    paddingHorizontal: 16,
    paddingVertical: 10,
    borderBottomWidth: 1,
    borderBottomColor: colors.border,
  },
  tableHeaderCell: {
    fontSize: 8,
    fontFamily: 'Helvetica-Bold',
    color: colors.textMuted,
    letterSpacing: 0.8,
    textTransform: 'uppercase',
  },
  tableRow: {
    flexDirection: 'row',
    paddingHorizontal: 16,
    paddingVertical: 14,
    borderBottomWidth: 1,
    borderBottomColor: colors.border,
  },
  tableCell: {
    fontSize: 10,
    color: colors.textPrimary,
  },
  tableCellMuted: {
    fontSize: 10,
    color: colors.textSecondary,
  },
  col60: { flex: 6 },
  col20: { flex: 2, textAlign: 'right' as const },
  col20Center: { flex: 2, textAlign: 'center' as const },
  totalRow: {
    flexDirection: 'row',
    justifyContent: 'flex-end',
    marginBottom: 6,
  },
  totalLabel: {
    fontSize: 11,
    color: colors.textSecondary,
    marginRight: 32,
  },
  totalValue: {
    fontSize: 11,
    fontFamily: 'Helvetica-Bold',
    color: colors.white,
    minWidth: 100,
    textAlign: 'right' as const,
  },
  grandTotalRow: {
    flexDirection: 'row',
    justifyContent: 'flex-end',
    marginTop: 8,
    paddingTop: 12,
    borderTopWidth: 1,
    borderTopColor: colors.border,
  },
  grandTotalLabel: {
    fontSize: 13,
    fontFamily: 'Helvetica-Bold',
    color: colors.textSecondary,
    marginRight: 32,
  },
  grandTotalValue: {
    fontSize: 15,
    fontFamily: 'Helvetica-Bold',
    color: colors.accent,
    minWidth: 100,
    textAlign: 'right' as const,
  },
  statusBadge: {
    paddingHorizontal: 8,
    paddingVertical: 4,
    borderRadius: 4,
    alignSelf: 'flex-start',
    marginTop: 6,
  },
  statusText: {
    fontSize: 9,
    fontFamily: 'Helvetica-Bold',
    letterSpacing: 0.5,
    color: colors.white,
  },
  paymentBox: {
    backgroundColor: colors.surface,
    borderRadius: 8,
    padding: 16,
    borderWidth: 1,
    borderColor: colors.border,
    marginBottom: 24,
  },
  paymentRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: 8,
  },
  paymentKey: {
    fontSize: 9,
    color: colors.textMuted,
  },
  paymentValue: {
    fontSize: 9,
    color: colors.textSecondary,
    fontFamily: 'Helvetica-Bold',
    maxWidth: 280,
    textAlign: 'right' as const,
  },
  footer: {
    position: 'absolute',
    bottom: 32,
    left: 48,
    right: 48,
    borderTopWidth: 1,
    borderTopColor: colors.border,
    paddingTop: 12,
    flexDirection: 'row',
    justifyContent: 'space-between',
  },
  footerText: {
    fontSize: 8,
    color: colors.textMuted,
  },
})

function fmt(amount: number, currency: string) {
  return `${(amount / 100).toFixed(2)} ${currency}`
}

function fmtDate(iso: string | null | undefined) {
  if (!iso) return '-'
  return new Date(iso).toLocaleDateString('en-GB', { day: '2-digit', month: 'long', year: 'numeric' })
}

function formatAddress(address: any): string {
  if (!address) return ''
  if (typeof address === 'string') return address
  if (typeof address.formatted === 'string') return address.formatted
  const parts = [address.street, address.city, address.region, address.country, address.zip]
  return parts.filter(Boolean).join(', ')
}

function pdfText(value: unknown) {
  return String(value ?? '')
    .normalize('NFKD')
    .replace(/[\u0300-\u036f]/g, '')
    .replace(/[\u2013\u2014]/g, '-')
    .replace(/\u00d7/g, 'x')
    .replace(/[^\x20-\x7E]/g, '')
}

function InvoiceDocument({ data }: { data: InvoiceData }) {
  const statusColor = STATUS_COLORS[data.status] ?? '#6b7280'
  const addressStr = formatAddress(data.company.address)
  const planLabel = data.subscription ? (PLAN_LABEL[data.subscription.plan] ?? data.subscription.plan) : 'Manual'
  const periodLabel = data.subscription ? (PERIOD_LABEL[data.subscription.billingPeriod] ?? data.subscription.billingPeriod) : 'Custom'
  const lineItems = data.lineItems?.length
    ? data.lineItems
    : [{
        description: `${planLabel} Plan — ${periodLabel} Subscription`,
        amount: data.amount,
        currency: data.currency,
        periodStart: data.subscription?.currentPeriodStart ?? null,
        periodEnd: data.subscription?.currentPeriodEnd ?? null,
      }]
  const totals = data.totals ?? {
    subtotalAmount: data.amount,
    discountAmount: 0,
    creditAmount: 0,
    taxAmount: 0,
    totalAmount: data.amount,
    amountPaid: data.paidAt ? data.amount : 0,
    amountDue: data.paidAt ? 0 : data.amount,
  }

  return React.createElement(
    Document,
    { author: 'RentalDriveGo', title: `Invoice ${data.invoiceNumber}`, subject: 'Subscription Invoice' },
    React.createElement(
      Page,
      { size: 'A4', style: s.page },

      // ── Header ──────────────────────────────────────────────────
      React.createElement(
        View,
        { style: s.header },
        React.createElement(
          View,
          null,
          React.createElement(Text, { style: s.brandName }, 'RentalDriveGo'),
          React.createElement(Text, { style: s.brandTagline }, 'Car Rental Management Platform'),
        ),
        React.createElement(
          View,
          { style: s.invoiceMeta },
          React.createElement(Text, { style: s.invoiceTitle }, 'INVOICE'),
          React.createElement(Text, { style: s.invoiceNumber }, pdfText(data.invoiceNumber)),
          React.createElement(
            View,
            { style: [s.statusBadge, { backgroundColor: statusColor }] },
            React.createElement(Text, { style: s.statusText }, pdfText(data.status)),
          ),
        ),
      ),

      // ── Bill To / Invoice Dates ──────────────────────────────────
      React.createElement(
        View,
        { style: s.row },
        React.createElement(
          View,
          { style: s.col },
          React.createElement(Text, { style: s.colLabel }, 'Bill To'),
          React.createElement(Text, { style: s.companyName }, pdfText(data.company.name)),
          React.createElement(Text, { style: s.companyDetail }, pdfText(data.company.email)),
          data.company.phone
            ? React.createElement(Text, { style: s.companyDetail }, pdfText(data.company.phone))
            : null,
          addressStr
            ? React.createElement(Text, { style: [s.companyDetail, { marginTop: 4 }] }, pdfText(addressStr))
            : null,
        ),
        React.createElement(
          View,
          { style: s.col },
          React.createElement(Text, { style: s.colLabel }, 'Invoice Details'),
          React.createElement(
            View,
            { style: s.metaRow },
            React.createElement(Text, { style: s.metaKey }, 'Invoice Number'),
            React.createElement(Text, { style: s.metaValue }, pdfText(data.invoiceNumber)),
          ),
          React.createElement(
            View,
            { style: s.metaRow },
            React.createElement(Text, { style: s.metaKey }, 'Issue Date'),
            React.createElement(Text, { style: s.metaValue }, fmtDate(data.issueDate)),
          ),
          data.dueDate
            ? React.createElement(
                View,
                { style: s.metaRow },
                React.createElement(Text, { style: s.metaKey }, 'Due Date'),
                React.createElement(Text, { style: s.metaValue }, fmtDate(data.dueDate)),
              )
            : null,
          React.createElement(
            View,
            { style: s.metaRow },
            React.createElement(Text, { style: s.metaKey }, 'Currency'),
            React.createElement(Text, { style: s.metaValue }, pdfText(data.currency)),
          ),
          React.createElement(
            View,
            { style: s.metaRow },
            React.createElement(Text, { style: s.metaKey }, 'Billing Period'),
            React.createElement(Text, { style: s.metaValue }, pdfText(periodLabel)),
          ),
          data.subscription
            ? React.createElement(
                View,
                { style: s.metaRow },
                React.createElement(Text, { style: s.metaKey }, 'Plan'),
                React.createElement(Text, { style: s.metaValue }, pdfText(planLabel)),
              )
            : null,
        ),
      ),

      // ── Line Items ───────────────────────────────────────────────
      React.createElement(
        View,
        { style: s.table },
        React.createElement(
          View,
          { style: s.tableHeader },
          React.createElement(Text, { style: [s.tableHeaderCell, s.col60] }, 'Description'),
          React.createElement(Text, { style: [s.tableHeaderCell, s.col20Center] }, 'Period'),
          React.createElement(Text, { style: [s.tableHeaderCell, s.col20] }, 'Amount'),
        ),
        ...lineItems.map((item) => {
          const periodStr = item.periodStart && item.periodEnd
            ? `${fmtDate(item.periodStart)} - ${fmtDate(item.periodEnd)}`
            : '-'
          const description = item.quantity && item.quantity > 1 && item.unitAmount !== undefined
            ? `${item.description} (${item.quantity} x ${fmt(item.unitAmount, item.currency)})`
            : item.description
          return React.createElement(
            View,
            { key: `${item.description}-${item.amount}-${item.periodStart ?? ''}`, style: s.tableRow },
            React.createElement(Text, { style: [s.tableCell, s.col60] }, pdfText(description)),
            React.createElement(Text, { style: [s.tableCellMuted, s.col20Center, { textAlign: 'center' }] }, pdfText(periodStr)),
            React.createElement(Text, { style: [s.tableCell, s.col20, { textAlign: 'right' }] }, pdfText(fmt(item.amount, item.currency))),
          )
        }),
      ),

      // ── Totals ───────────────────────────────────────────────────
      React.createElement(
        View,
        { style: s.totalRow },
        React.createElement(Text, { style: s.totalLabel }, 'Subtotal'),
        React.createElement(Text, { style: s.totalValue }, fmt(totals.subtotalAmount, data.currency)),
      ),
      totals.discountAmount > 0
        ? React.createElement(
            View,
            { style: s.totalRow },
            React.createElement(Text, { style: s.totalLabel }, 'Discounts'),
            React.createElement(Text, { style: s.totalValue }, `- ${fmt(totals.discountAmount, data.currency)}`),
          )
        : null,
      totals.creditAmount > 0
        ? React.createElement(
            View,
            { style: s.totalRow },
            React.createElement(Text, { style: s.totalLabel }, 'Credits'),
            React.createElement(Text, { style: s.totalValue }, `- ${fmt(totals.creditAmount, data.currency)}`),
          )
        : null,
      totals.taxAmount > 0
        ? React.createElement(
            View,
            { style: s.totalRow },
            React.createElement(Text, { style: s.totalLabel }, 'Tax'),
            React.createElement(Text, { style: s.totalValue }, fmt(totals.taxAmount, data.currency)),
          )
        : null,
      React.createElement(
        View,
        { style: s.grandTotalRow },
        React.createElement(Text, { style: s.grandTotalLabel }, 'Total Due'),
        React.createElement(Text, { style: s.grandTotalValue }, fmt(totals.totalAmount, data.currency)),
      ),

      // ── Payment Info ─────────────────────────────────────────────
      React.createElement(
        View,
        { style: [s.paymentBox, { marginTop: 24 }] },
        React.createElement(Text, { style: [s.colLabel, { marginBottom: 10 }] }, 'Payment Information'),
        React.createElement(
          View,
          { style: s.paymentRow },
          React.createElement(Text, { style: s.paymentKey }, 'Payment Provider'),
          React.createElement(Text, { style: s.paymentValue }, pdfText(data.paymentProvider)),
        ),
        data.transactionId
          ? React.createElement(
              View,
              { style: s.paymentRow },
              React.createElement(Text, { style: s.paymentKey }, 'Transaction ID'),
              React.createElement(Text, { style: s.paymentValue }, pdfText(data.transactionId)),
            )
          : null,
        React.createElement(
          View,
          { style: s.paymentRow },
          React.createElement(Text, { style: s.paymentKey }, 'Payment Date'),
          React.createElement(Text, { style: s.paymentValue }, fmtDate(data.paidAt)),
        ),
        React.createElement(
          View,
          { style: s.paymentRow },
          React.createElement(Text, { style: s.paymentKey }, 'Status'),
          React.createElement(Text, { style: [s.paymentValue, { color: statusColor }] }, pdfText(data.status)),
        ),
      ),

      // ── Footer ───────────────────────────────────────────────────
      React.createElement(
        View,
        { style: s.footer },
        React.createElement(Text, { style: s.footerText }, 'RentalDriveGo - Car Rental Management Platform'),
        React.createElement(Text, { style: s.footerText }, `Generated on ${fmtDate(new Date().toISOString())}`),
      ),
    ),
  )
}

export async function generateInvoicePdf(data: InvoiceData): Promise<Buffer> {
  const doc = React.createElement(InvoiceDocument, { data })
  try {
    const buffer = await renderToBuffer(doc as any)
    return buffer as unknown as Buffer
  } catch {
    return buildSimpleInvoicePdf(data)
  }
}

export function buildInvoiceNumber(invoiceId: string, createdAt: Date): string {
  const year = createdAt.getFullYear()
  const short = invoiceId.slice(-6).toUpperCase()
  return `INV-${year}-${short}`
}

function pdfEscape(value: unknown) {
  return pdfText(value).replace(/\\/g, '\\\\').replace(/\(/g, '\\(').replace(/\)/g, '\\)')
}

function buildSimpleInvoicePdf(data: InvoiceData) {
  const lineItems = data.lineItems?.length
    ? data.lineItems
    : [{ description: 'Invoice charge', amount: data.amount, currency: data.currency }]
  const totals = data.totals ?? {
    subtotalAmount: data.amount,
    discountAmount: 0,
    creditAmount: 0,
    taxAmount: 0,
    totalAmount: data.amount,
    amountPaid: data.paidAt ? data.amount : 0,
    amountDue: data.paidAt ? 0 : data.amount,
  }
  const address = formatAddress(data.company.address)
  const lines = [
    'RentalDriveGo - Invoice',
    `Invoice Number: ${data.invoiceNumber}`,
    `Status: ${data.status}`,
    `Issue Date: ${fmtDate(data.issueDate)}`,
    data.dueDate ? `Due Date: ${fmtDate(data.dueDate)}` : null,
    `Bill To: ${data.company.name}`,
    `Email: ${data.company.email}`,
    data.company.phone ? `Phone: ${data.company.phone}` : null,
    address ? `Address: ${address}` : null,
    '',
    'Line Items',
    ...lineItems.map((item) => `${item.description} - ${fmt(item.amount, item.currency)}`),
    '',
    `Subtotal: ${fmt(totals.subtotalAmount, data.currency)}`,
    totals.discountAmount ? `Discounts: -${fmt(totals.discountAmount, data.currency)}` : null,
    totals.creditAmount ? `Credits: -${fmt(totals.creditAmount, data.currency)}` : null,
    totals.taxAmount ? `Tax: ${fmt(totals.taxAmount, data.currency)}` : null,
    `Total: ${fmt(totals.totalAmount, data.currency)}`,
    `Amount Paid: ${fmt(totals.amountPaid, data.currency)}`,
    `Amount Due: ${fmt(totals.amountDue, data.currency)}`,
    '',
    `Payment Provider: ${data.paymentProvider}`,
    data.transactionId ? `Transaction ID: ${data.transactionId}` : null,
  ].filter((line): line is string => line !== null)

  const content = [
    'BT',
    '/F1 18 Tf',
    '50 790 Td',
    `(${pdfEscape(lines[0])}) Tj`,
    '/F1 10 Tf',
    ...lines.slice(1).flatMap((line) => ['0 -18 Td', `(${pdfEscape(line)}) Tj`]),
    'ET',
  ].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 >> >> /Contents 5 0 R >>',
    '<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>',
    `<< /Length ${Buffer.byteLength(content, 'utf8')} >>\nstream\n${content}\nendstream`,
  ]

  let pdf = '%PDF-1.4\n'
  const offsets = [0]
  objects.forEach((object, index) => {
    offsets.push(Buffer.byteLength(pdf, 'utf8'))
    pdf += `${index + 1} 0 obj\n${object}\nendobj\n`
  })
  const xrefOffset = Buffer.byteLength(pdf, 'utf8')
  pdf += `xref\n0 ${objects.length + 1}\n`
  pdf += '0000000000 65535 f \n'
  for (let i = 1; i < offsets.length; i += 1) {
    pdf += `${String(offsets[i]).padStart(10, '0')} 00000 n \n`
  }
  pdf += `trailer\n<< /Size ${objects.length + 1} /Root 1 0 R >>\nstartxref\n${xrefOffset}\n%%EOF\n`

  return Buffer.from(pdf, 'utf8')
}
