import { Injectable } from '@nestjs/common'
import * as PDFDocument from 'pdfkit'
import { InvoiceDocument } from '../common/schemas'
import { ClientFolderDocument } from '../common/schemas'

// ─── Colours & fonts ──────────────────────────────────────────────────────────

const TEAL   = '#0D9394'
const DARK   = '#1A1A2E'
const GREY   = '#6B7280'
const LGREY  = '#E5E7EB'
const WHITE  = '#FFFFFF'

function fmtMoney(n: number, currency = 'THB') {
  return new Intl.NumberFormat('en-TH', { style: 'currency', currency, maximumFractionDigits: 2 }).format(n)
}
function fmtDate(d: Date | string) {
  return new Date(d).toLocaleDateString('en-GB', { day: 'numeric', month: 'long', year: 'numeric' })
}

@Injectable()
export class InvoicePdfService {

  async generate(invoice: InvoiceDocument, folder: ClientFolderDocument): Promise<Buffer> {
    return new Promise((resolve, reject) => {
      const doc = new PDFDocument({ size: 'A4', margin: 50 })
      const chunks: Buffer[] = []
      doc.on('data', c => chunks.push(c))
      doc.on('end', () => resolve(Buffer.concat(chunks)))
      doc.on('error', reject)

      this.buildDocument(doc, invoice, folder)
      doc.end()
    })
  }

  private buildDocument(doc: PDFKit.PDFDocument, invoice: InvoiceDocument, folder: ClientFolderDocument) {
    const pageW = doc.page.width - 100   // usable width (margins 50 each side)

    // ── Header bar ──────────────────────────────────────────────────────────
    doc.rect(50, 50, pageW, 70).fill(TEAL)

    doc.fillColor(WHITE).fontSize(22).font('Helvetica-Bold')
       .text('GPS LEGAL', 65, 65)
    doc.fontSize(9).font('Helvetica')
       .text('Legal Counsel · Bangkok, Thailand', 65, 92)

    // Invoice label on right side of header
    doc.fontSize(22).font('Helvetica-Bold')
       .text('INVOICE', 0, 65, { align: 'right' })
    doc.fontSize(10).font('Helvetica')
       .text(invoice.invoiceNumber, 0, 92, { align: 'right' })

    // ── Client + invoice meta block ──────────────────────────────────────────
    let y = 140

    // Left: bill to
    doc.fillColor(GREY).fontSize(8).font('Helvetica-Bold')
       .text('BILL TO', 50, y)
    doc.fillColor(DARK).fontSize(11).font('Helvetica-Bold')
       .text(folder.displayName, 50, y + 14)

    const email = folder.emails?.[0]?.address ?? folder.email
    const phone = folder.phones?.[0]
      ? `${folder.phones[0].dialCode} ${folder.phones[0].number}`
      : folder.phone

    let contactY = y + 30
    doc.fontSize(9).font('Helvetica').fillColor(GREY)
    if (folder.address) { doc.text(folder.address, 50, contactY); contactY += 13 }
    if (email)          { doc.text(email,           50, contactY); contactY += 13 }
    if (phone)          { doc.text(phone,            50, contactY) }

    // Right: invoice meta table
    const col1 = 370, col2 = 470
    const metaRows = [
      ['Invoice No.',  invoice.invoiceNumber],
      ['Issue Date',   fmtDate(invoice.issueDate)],
      ['Due Date',     fmtDate(invoice.dueDate)],
      ['Currency',     invoice.currency ?? 'THB'],
    ]

    doc.fillColor(GREY).fontSize(8).font('Helvetica-Bold')
       .text('INVOICE DETAILS', col1, y)

    let mY = y + 14
    for (const [label, value] of metaRows) {
      doc.font('Helvetica').fontSize(8).fillColor(GREY).text(label, col1, mY)
      doc.font('Helvetica-Bold').fontSize(9).fillColor(DARK).text(value, col2, mY)
      mY += 15
    }

    // ── Matter reference ─────────────────────────────────────────────────────
    y = Math.max(contactY, mY) + 20

    if ((invoice as any).matterId) {
      doc.rect(50, y, pageW, 22).fill('#F3F4F6')
      doc.fillColor(GREY).fontSize(8).font('Helvetica')
         .text('MATTER REFERENCE', 58, y + 7)
      y += 30
    }

    // ── Line items table ─────────────────────────────────────────────────────
    y += 10

    // Table header
    doc.rect(50, y, pageW, 22).fill(DARK)
    const cols = { desc: 58, qty: 320, unit: 380, amount: 450 }

    doc.fillColor(WHITE).fontSize(8).font('Helvetica-Bold')
    doc.text('DESCRIPTION',  cols.desc,   y + 7)
    doc.text('HRS / QTY',    cols.qty,    y + 7, { width: 55, align: 'right' })
    doc.text('RATE',         cols.unit,   y + 7, { width: 65, align: 'right' })
    doc.text('AMOUNT',       cols.amount, y + 7, { width: 95, align: 'right' })

    y += 22

    let rowAlt = false
    for (const item of invoice.lineItems) {
      const rowH = 22
      if (rowAlt) doc.rect(50, y, pageW, rowH).fill('#F9FAFB')
      rowAlt = !rowAlt

      doc.fillColor(DARK).fontSize(9).font('Helvetica')
         .text(item.description, cols.desc, y + 6, { width: 255, ellipsis: true })
      doc.text(
        item.quantity.toFixed(2),
        cols.qty, y + 6, { width: 55, align: 'right' }
      )
      doc.text(
        fmtMoney(item.unitPrice, invoice.currency),
        cols.unit, y + 6, { width: 65, align: 'right' }
      )
      doc.font('Helvetica-Bold')
         .text(
           fmtMoney(item.amount, invoice.currency),
           cols.amount, y + 6, { width: 95, align: 'right' }
         )

      y += rowH
    }

    // Divider
    doc.moveTo(50, y).lineTo(50 + pageW, y).strokeColor(LGREY).lineWidth(1).stroke()
    y += 12

    // ── Totals block ─────────────────────────────────────────────────────────
    const totX = 380

    const addTotal = (label: string, value: string, bold = false, color = DARK) => {
      doc.font(bold ? 'Helvetica-Bold' : 'Helvetica')
         .fontSize(bold ? 11 : 9)
         .fillColor(GREY).text(label, totX, y, { width: 90 })
      doc.fillColor(color).text(value, totX + 95, y, { width: pageW - totX - 93, align: 'right' })
      y += bold ? 18 : 15
    }

    addTotal('Subtotal',  fmtMoney(invoice.subtotal, invoice.currency))

    if (!invoice.vatRate || invoice.vatRate === 0) {
      addTotal('VAT', 'Exempt')
    } else {
      addTotal(`VAT (${(invoice.vatRate * 100).toFixed(0)}%)`, fmtMoney(invoice.vatAmount, invoice.currency))
    }

    y += 4
    doc.moveTo(totX, y).lineTo(50 + pageW, y).strokeColor(LGREY).lineWidth(0.5).stroke()
    y += 6

    addTotal('TOTAL DUE', fmtMoney(invoice.total, invoice.currency), true, TEAL)

    if (invoice.status === 'paid') {
      y += 4
      doc.rect(totX, y, pageW - totX + 2, 22).fill('#EEFBE5')
      doc.fillColor('#71DD37').fontSize(10).font('Helvetica-Bold')
         .text('PAID', totX + 4, y + 6)
      if (invoice.paidDate) {
        doc.fillColor(GREY).fontSize(8).font('Helvetica')
           .text(fmtDate(invoice.paidDate), totX + 50, y + 8)
      }
      y += 28
    }

    // ── Payment details ───────────────────────────────────────────────────────
    y += 20
    doc.moveTo(50, y).lineTo(50 + pageW, y).strokeColor(LGREY).lineWidth(1).stroke()
    y += 14

    doc.fillColor(GREY).fontSize(8).font('Helvetica-Bold').text('PAYMENT DETAILS', 50, y)
    y += 14
    doc.fillColor(DARK).fontSize(9).font('Helvetica')
       .text('Bank: Kasikorn Bank (KBank)  |  Account Name: GPS Legal Co., Ltd.', 50, y)
    y += 13
    doc.text('Account No: 123-4-56789-0  |  Branch: Silom  |  SWIFT: KASITHBK', 50, y)
    y += 13
    doc.fillColor(GREY).fontSize(8)
       .text(`Please reference invoice number ${invoice.invoiceNumber} with your payment.`, 50, y)

    // ── Notes ────────────────────────────────────────────────────────────────
    if (invoice.notes) {
      y += 20
      doc.fillColor(GREY).fontSize(8).font('Helvetica-Bold').text('NOTES', 50, y)
      y += 12
      doc.fillColor(DARK).fontSize(9).font('Helvetica').text(invoice.notes, 50, y, { width: pageW })
    }

    // ── Footer ───────────────────────────────────────────────────────────────
    const footerY = doc.page.height - 60
    doc.rect(50, footerY, pageW, 1).fill(LGREY)
    doc.fillColor(GREY).fontSize(7.5).font('Helvetica')
       .text(
         'GPS Legal Co., Ltd.  ·  Bangkok, Thailand  ·  This invoice is subject to Thai law.',
         50, footerY + 8, { align: 'center', width: pageW }
       )
  }
}
