/**
 * Génération de PDFs de factures via `@react-pdf/renderer` — composants
 * React déclaratifs, mêmes couleurs que le SPA, maintenable de bout en
 * bout sans switcher de mental model.
 *
 * Le `renderToBuffer(<InvoiceDocument …/>)` produit un Buffer uploadable
 * tel quel via `drive.use().put(key, buf)`.
 *
 * Polices : on reste sur Helvetica intégrée (pas besoin de loader des
 * fichiers TTF, ça simplifie la portabilité prod).
 */

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

// ---------------------------------------------------------------------------
// Types — exposés pour factories.ts
// ---------------------------------------------------------------------------

export type InvoiceItem = {
  description: string
  unit: string
  quantity: number
  unitPriceHtCents: number
}

export type PdfInvoiceInput = {
  seller: {
    name: string
    address: string
    siret: string | null
    tvaNumber: string | null
    email: string
    phone: string | null
    iban: string
  }
  client: {
    name: string
    contactFirstName: string | null
    contactLastName: string | null
    address: string | null
    siret: string | null
  }
  invoice: {
    numero: string
    issueDate: Date
    dueDate: Date
    items: InvoiceItem[]
    note?: string | null
  }
}

// ---------------------------------------------------------------------------
// Tokens de marque (cf. CLAUDE.md → palette)
// ---------------------------------------------------------------------------

const C = {
  rubis: '#9F1239',
  rubisDeep: '#771328',
  rubisGlow: '#FBE4EA',
  cream: '#FAF7F2',
  cream2: '#F5EFE7',
  ink: '#1A1410',
  ink2: '#4F4640',
  ink3: '#8A7F76',
  line: '#E8E0D6',
  white: '#FFFFFF',
} as const

// ---------------------------------------------------------------------------
// Helpers de formatage FR
// ---------------------------------------------------------------------------

const FR_DATE = new Intl.DateTimeFormat('fr-FR', {
  day: '2-digit',
  month: '2-digit',
  year: 'numeric',
})
function formatDate(d: Date): string {
  return FR_DATE.format(d)
}

const FR_EUROS = new Intl.NumberFormat('fr-FR', {
  style: 'currency',
  currency: 'EUR',
  minimumFractionDigits: 2,
})
function formatEuros(cents: number): string {
  return FR_EUROS.format(cents / 100)
}

// ---------------------------------------------------------------------------
// Styles
// ---------------------------------------------------------------------------

const styles = StyleSheet.create({
  page: {
    backgroundColor: C.white,
    fontFamily: 'Helvetica',
    fontSize: 10,
    color: C.ink,
    paddingBottom: 60,
  },

  // Header bandeau
  header: {
    backgroundColor: C.rubisDeep,
    color: C.white,
    paddingHorizontal: 48,
    paddingVertical: 32,
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'flex-start',
  },
  headerLeft: { flex: 1, paddingRight: 16 },
  sellerName: {
    fontFamily: 'Helvetica-Bold',
    fontSize: 20,
    marginBottom: 10,
  },
  sellerMeta: {
    fontSize: 8.5,
    color: C.cream2,
    lineHeight: 1.5,
  },
  headerRight: { width: 180, alignItems: 'flex-end' },
  factureLabel: {
    fontFamily: 'Helvetica-Bold',
    fontSize: 26,
    marginBottom: 8,
  },
  factureMeta: {
    fontSize: 9,
    color: C.cream2,
    lineHeight: 1.5,
  },

  // Addresses
  addresses: {
    paddingHorizontal: 48,
    paddingTop: 32,
    flexDirection: 'row',
    justifyContent: 'space-between',
  },
  addressBlock: { flex: 1 },
  addressBlockRight: { flex: 1, alignItems: 'flex-end' },
  eyebrow: {
    fontFamily: 'Helvetica-Bold',
    fontSize: 8,
    letterSpacing: 1,
    color: C.ink3,
    marginBottom: 6,
  },
  clientName: {
    fontFamily: 'Helvetica-Bold',
    fontSize: 13,
    color: C.ink,
    marginBottom: 4,
  },
  clientMeta: {
    fontSize: 9.5,
    color: C.ink2,
    lineHeight: 1.4,
  },
  clientSiret: {
    fontSize: 8,
    color: C.ink3,
    marginTop: 4,
  },
  dueDate: {
    fontFamily: 'Helvetica-Bold',
    fontSize: 15,
    color: C.rubis,
    marginBottom: 4,
  },
  dueDateSub: {
    fontSize: 9,
    color: C.ink3,
  },

  // Items table
  table: {
    marginTop: 36,
    paddingHorizontal: 48,
  },
  tableHeader: {
    backgroundColor: C.cream2,
    flexDirection: 'row',
    paddingVertical: 8,
    paddingHorizontal: 10,
  },
  th: {
    fontFamily: 'Helvetica-Bold',
    fontSize: 8.5,
    letterSpacing: 0.5,
    color: C.ink3,
  },
  tableRow: {
    flexDirection: 'row',
    paddingVertical: 10,
    paddingHorizontal: 10,
    borderBottomWidth: 0.5,
    borderBottomColor: C.line,
  },
  tdDescription: { flex: 5 },
  tdQty: { flex: 1, textAlign: 'right' },
  tdUnit: { flex: 1.5, textAlign: 'right' },
  tdTotal: { flex: 2, textAlign: 'right' },
  itemDesc: {
    fontSize: 10,
    color: C.ink,
  },
  itemUnit: {
    fontSize: 8,
    color: C.ink3,
    marginTop: 2,
  },

  // Totals
  totals: {
    marginTop: 18,
    paddingHorizontal: 48,
    flexDirection: 'row',
    justifyContent: 'flex-end',
  },
  totalsBlock: { width: 240 },
  totalRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    paddingVertical: 4,
  },
  totalLabel: {
    fontSize: 10,
    color: C.ink2,
  },
  totalValue: {
    fontFamily: 'Helvetica-Bold',
    fontSize: 10,
    color: C.ink,
  },
  totalTtcRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    backgroundColor: C.rubisGlow,
    paddingVertical: 10,
    paddingHorizontal: 12,
    marginTop: 8,
    alignItems: 'center',
  },
  totalTtcLabel: {
    fontFamily: 'Helvetica-Bold',
    fontSize: 11,
    color: C.rubisDeep,
  },
  totalTtcValue: {
    fontFamily: 'Helvetica-Bold',
    fontSize: 14,
    color: C.rubisDeep,
  },

  // Note libre
  note: {
    marginTop: 28,
    paddingHorizontal: 48,
    fontSize: 9,
    fontStyle: 'italic',
    color: C.ink3,
    lineHeight: 1.4,
  },

  // Footer fixe en bas de page
  footer: {
    position: 'absolute',
    bottom: 24,
    left: 48,
    right: 48,
    textAlign: 'center',
  },
  footerLine: {
    fontSize: 7.5,
    color: C.ink3,
    lineHeight: 1.5,
  },
  footerBrand: {
    fontSize: 7,
    color: C.ink3,
    marginTop: 4,
  },
})

// ---------------------------------------------------------------------------
// Composants
// ---------------------------------------------------------------------------

function InvoiceDocument({ data }: { data: PdfInvoiceInput }) {
  const totalHt = data.invoice.items.reduce(
    (s, i) => s + i.quantity * i.unitPriceHtCents,
    0
  )
  const tva = Math.round(totalHt * 0.2)
  const totalTtc = totalHt + tva

  const paymentTermDays = Math.round(
    DateTime.fromJSDate(data.invoice.dueDate)
      .startOf('day')
      .diff(
        DateTime.fromJSDate(data.invoice.issueDate).startOf('day'),
        'days'
      ).days
  )

  return (
    <Document
      title={`Facture ${data.invoice.numero}`}
      author={data.seller.name}
      creator="Rubis"
    >
      <Page size="A4" style={styles.page}>
        <Header data={data} />
        <Addresses data={data} paymentTermDays={paymentTermDays} />
        <ItemsTable items={data.invoice.items} />
        <Totals totalHt={totalHt} tva={tva} totalTtc={totalTtc} />
        {data.invoice.note ? <Text style={styles.note}>{data.invoice.note}</Text> : null}
        <Footer iban={data.seller.iban} />
      </Page>
    </Document>
  )
}

function Header({ data }: { data: PdfInvoiceInput }) {
  return (
    <View style={styles.header}>
      <View style={styles.headerLeft}>
        <Text style={styles.sellerName}>{data.seller.name}</Text>
        <Text style={styles.sellerMeta}>
          {data.seller.address} · {data.seller.email}
          {data.seller.phone ? ` · ${data.seller.phone}` : ''}
        </Text>
        {data.seller.siret ? (
          <Text style={styles.sellerMeta}>
            SIRET {data.seller.siret}
            {data.seller.tvaNumber ? ` · TVA ${data.seller.tvaNumber}` : ''}
          </Text>
        ) : null}
      </View>
      <View style={styles.headerRight}>
        <Text style={styles.factureLabel}>FACTURE</Text>
        <Text style={styles.factureMeta}>N° {data.invoice.numero}</Text>
        <Text style={styles.factureMeta}>
          Émise le {formatDate(data.invoice.issueDate)}
        </Text>
      </View>
    </View>
  )
}

function Addresses({
  data,
  paymentTermDays,
}: {
  data: PdfInvoiceInput
  paymentTermDays: number
}) {
  const { client } = data
  const contactName = [client.contactFirstName, client.contactLastName]
    .filter(Boolean)
    .join(' ')

  return (
    <View style={styles.addresses}>
      <View style={styles.addressBlock}>
        <Text style={styles.eyebrow}>ADRESSÉE À</Text>
        <Text style={styles.clientName}>{client.name}</Text>
        {contactName ? (
          <Text style={styles.clientMeta}>À l'attention de {contactName}</Text>
        ) : null}
        {client.address ? (
          <Text style={styles.clientMeta}>{client.address}</Text>
        ) : null}
        {client.siret ? (
          <Text style={styles.clientSiret}>SIRET {client.siret}</Text>
        ) : null}
      </View>
      <View style={styles.addressBlockRight}>
        <Text style={styles.eyebrow}>ÉCHÉANCE</Text>
        <Text style={styles.dueDate}>{formatDate(data.invoice.dueDate)}</Text>
        <Text style={styles.dueDateSub}>Soit {paymentTermDays} jours</Text>
      </View>
    </View>
  )
}

function ItemsTable({ items }: { items: InvoiceItem[] }) {
  return (
    <View style={styles.table}>
      <View style={styles.tableHeader}>
        <Text style={[styles.th, styles.tdDescription]}>DÉSIGNATION</Text>
        <Text style={[styles.th, styles.tdQty]}>QTÉ</Text>
        <Text style={[styles.th, styles.tdUnit]}>P.U. HT</Text>
        <Text style={[styles.th, styles.tdTotal]}>TOTAL HT</Text>
      </View>
      {items.map((item, idx) => {
        const itemTotalHt = item.quantity * item.unitPriceHtCents
        return (
          <View key={idx} style={styles.tableRow}>
            <View style={styles.tdDescription}>
              <Text style={styles.itemDesc}>{item.description}</Text>
              <Text style={styles.itemUnit}>{item.unit}</Text>
            </View>
            <Text style={[styles.itemDesc, styles.tdQty]}>{item.quantity}</Text>
            <Text style={[styles.itemDesc, styles.tdUnit]}>
              {formatEuros(item.unitPriceHtCents)}
            </Text>
            <Text style={[styles.itemDesc, styles.tdTotal]}>
              {formatEuros(itemTotalHt)}
            </Text>
          </View>
        )
      })}
    </View>
  )
}

function Totals({
  totalHt,
  tva,
  totalTtc,
}: {
  totalHt: number
  tva: number
  totalTtc: number
}) {
  return (
    <View style={styles.totals}>
      <View style={styles.totalsBlock}>
        <View style={styles.totalRow}>
          <Text style={styles.totalLabel}>Total HT</Text>
          <Text style={styles.totalValue}>{formatEuros(totalHt)}</Text>
        </View>
        <View style={styles.totalRow}>
          <Text style={styles.totalLabel}>TVA 20%</Text>
          <Text style={styles.totalValue}>{formatEuros(tva)}</Text>
        </View>
        <View style={styles.totalTtcRow}>
          <Text style={styles.totalTtcLabel}>TOTAL TTC</Text>
          <Text style={styles.totalTtcValue}>{formatEuros(totalTtc)}</Text>
        </View>
      </View>
    </View>
  )
}

function Footer({ iban }: { iban: string }) {
  return (
    <View style={styles.footer} fixed>
      <Text style={styles.footerLine}>
        Règlement par virement IBAN {iban} · Pénalités de retard : 3× taux légal
        · Indemnité forfaitaire 40 € (art. L.441-10 C. com.)
      </Text>
      <Text style={styles.footerBrand}>Émise via Rubis sur l'ongle</Text>
    </View>
  )
}

// ---------------------------------------------------------------------------
// API publique
// ---------------------------------------------------------------------------

export async function generateInvoicePdfBuffer(
  data: PdfInvoiceInput
): Promise<Buffer> {
  return renderToBuffer(<InvoiceDocument data={data} />)
}
