import { useEffect, useRef, useState } from 'react'
import { useQuery } from '@tanstack/react-query'
import { queryOptions } from '@tanstack/react-query'
import { api } from '@/lib/api-client'
import { usePOSStore } from '@/stores/pos.store'
import JsBarcode from 'jsbarcode'

interface ReceiptLineItem {
  description: string
  qty: number
  unitPrice: string
  taxAmount: string
  lineTotal: string
  discountAmount?: string
}

interface ReceiptData {
  transaction: {
    transactionNumber: string
    transactionType: string
    status: string
    subtotal: string
    discountTotal: string
    taxTotal: string
    total: string
    paymentMethod: string | null
    amountTendered: string | null
    changeGiven: string | null
    roundingAdjustment: string
    completedAt: string | null
    createdAt: string
    lineItems: ReceiptLineItem[]
  }
  company: {
    name: string
    phone: string | null
    email: string | null
    address: { street?: string; city?: string; state?: string; zip?: string } | null
  }
  location: {
    name: string
    phone: string | null
    email: string | null
    address: { street?: string; city?: string; state?: string; zip?: string } | null
  }
}

interface ReceiptConfig {
  header?: string
  footer?: string
  returnPolicy?: string
  social?: string
}

interface POSReceiptProps {
  data: ReceiptData
  size?: 'thermal' | 'full'
  footerText?: string
  config?: ReceiptConfig
}

function useStoreLogo(companyId?: string) {
  const token = usePOSStore((s) => s.token)
  const [logoSrc, setLogoSrc] = useState<string | null>(null)

  const { data: storeData } = useQuery(queryOptions({
    queryKey: ['store'],
    queryFn: () => api.get<{ id: string }>('/v1/store'),
    enabled: !!token,
  }))

  const storeId = companyId ?? storeData?.id
  const { data: filesData } = useQuery(queryOptions({
    queryKey: ['files', 'company', storeId ?? ''],
    queryFn: () => api.get<{ data: { id: string; path: string }[] }>('/v1/files', { entityType: 'company', entityId: storeId }),
    enabled: !!storeId,
  }))

  const logoFile = filesData?.data?.find((f) => f.path.includes('/logo-'))

  useEffect(() => {
    if (!logoFile || !token) { setLogoSrc(null); return }
    let cancelled = false
    let blobUrl: string | null = null
    async function load() {
      try {
        const res = await fetch(`/v1/files/serve/${logoFile!.path}`, {
          headers: { Authorization: `Bearer ${token}` },
        })
        if (!res.ok || cancelled) return
        const blob = await res.blob()
        if (!cancelled) { blobUrl = URL.createObjectURL(blob); setLogoSrc(blobUrl) }
      } catch { /* ignore */ }
    }
    load()
    return () => { cancelled = true; if (blobUrl) URL.revokeObjectURL(blobUrl) }
  }, [logoFile?.path, token])

  return logoSrc
}

export function POSReceipt({ data, size = 'thermal', footerText, config }: POSReceiptProps) {
  const isThermal = size === 'thermal'

  if (!isThermal) {
    return <FullPageReceipt data={data} config={config} footerText={footerText} />
  }

  return <ThermalReceipt data={data} config={config} footerText={footerText} />
}

function useReceiptData(data: POSReceiptProps['data']) {
  const { transaction: txn, company, location } = data
  return {
    txn,
    company,
    location,
    date: new Date(txn.completedAt ?? txn.createdAt),
    subtotal: parseFloat(txn.subtotal),
    discountTotal: parseFloat(txn.discountTotal),
    taxTotal: parseFloat(txn.taxTotal),
    total: parseFloat(txn.total),
    rounding: parseFloat(txn.roundingAdjustment),
    tendered: txn.amountTendered ? parseFloat(txn.amountTendered) : null,
    change: txn.changeGiven ? parseFloat(txn.changeGiven) : null,
    addr: location.address ?? company.address,
    phone: location.phone ?? company.phone,
    email: location.email ?? company.email,
  }
}

function useBarcode(ref: React.RefObject<SVGSVGElement | null>, value: string, opts: { width: number; height: number; fontSize: number }) {
  useEffect(() => {
    if (ref.current) {
      try {
        JsBarcode(ref.current, value, { format: 'CODE128', displayValue: true, margin: 4, ...opts })
      } catch { /* barcode generation failed — show text fallback */ }
    }
  }, [value])
}

function ThermalReceipt({ data, config, footerText }: { data: POSReceiptProps['data']; config?: ReceiptConfig; footerText?: string }) {
  const barcodeRef = useRef<SVGSVGElement>(null)
  const logoSrc = useStoreLogo()
  const { txn, company, location, date, subtotal, discountTotal, taxTotal, total, rounding, tendered, change, addr, phone } = useReceiptData(data)
  useBarcode(barcodeRef, txn.transactionNumber, { width: 1.5, height: 40, fontSize: 10 })

  const s = {
    row: { display: 'flex', justifyContent: 'space-between' } as const,
    section: { padding: '8px 0', borderBottom: '1px dashed #999' } as const,
    gray: { color: '#666' } as const,
    light: { color: '#999' } as const,
    bold: { fontWeight: 'bold' } as const,
    center: { textAlign: 'center' } as const,
    nums: { fontVariantNumeric: 'tabular-nums' } as const,
  }

  return (
    <div style={{
      background: '#fff', color: '#000', fontFamily: 'monospace',
      width: 260, maxWidth: 260, fontSize: 10, lineHeight: '1.3', margin: '0 auto',
    }}>
      {/* Store header */}
      <div style={{ ...s.section, ...s.center }}>
        {logoSrc ? (
          <img src={logoSrc} alt={company.name} style={{ display: 'block', margin: '0 auto 4px', maxHeight: 48, maxWidth: 200, objectFit: 'contain' }} />
        ) : (
          <div style={{ ...s.bold, fontSize: 14 }}>{company.name}</div>
        )}
        {location.name !== company.name && <div style={s.gray}>{location.name}</div>}
        {addr?.street && <div>{addr.street}</div>}
        {(addr?.city || addr?.state || addr?.zip) && (
          <div>{[addr?.city, addr?.state].filter(Boolean).join(', ')} {addr?.zip}</div>
        )}
        {phone && <div>{phone}</div>}
        {config?.header && <div style={{ ...s.gray, marginTop: 4 }}>{config.header}</div>}
      </div>

      {/* Transaction info */}
      <div style={s.section}>
        <div style={s.row}>
          <span>{txn.transactionNumber}</span>
          <span>{txn.transactionType.replace('_', ' ')}</span>
        </div>
        <div style={{ ...s.row, ...s.gray }}>
          <span>{date.toLocaleDateString()}</span>
          <span>{date.toLocaleTimeString()}</span>
        </div>
      </div>

      {/* Line items */}
      <div style={s.section}>
        {txn.lineItems.map((item, i) => (
          <div key={i} style={{ padding: '2px 0' }}>
            <div style={s.row}>
              <span style={{ flex: 1, paddingRight: 8 }}>{item.description}</span>
              <span style={s.nums}>${parseFloat(item.lineTotal).toFixed(2)}</span>
            </div>
            {(item.qty > 1 || parseFloat(item.discountAmount ?? '0') > 0) && (
              <div style={{ ...s.light, paddingLeft: 8 }}>
                {item.qty > 1 && <span>{item.qty} x ${parseFloat(item.unitPrice).toFixed(2)}</span>}
                {parseFloat(item.discountAmount ?? '0') > 0 && (
                  <span style={{ marginLeft: 8 }}>disc -${parseFloat(item.discountAmount!).toFixed(2)}</span>
                )}
              </div>
            )}
          </div>
        ))}
      </div>

      {/* Totals */}
      <div style={s.section}>
        <div style={s.row}><span>Subtotal</span><span style={s.nums}>${subtotal.toFixed(2)}</span></div>
        {discountTotal > 0 && (
          <div style={s.row}><span>Discount</span><span style={s.nums}>-${discountTotal.toFixed(2)}</span></div>
        )}
        <div style={s.row}><span>Tax</span><span style={s.nums}>${taxTotal.toFixed(2)}</span></div>
        {rounding !== 0 && (
          <div style={{ ...s.row, ...s.gray }}><span>Rounding</span><span style={s.nums}>{rounding > 0 ? '+' : ''}{rounding.toFixed(2)}</span></div>
        )}
        <div style={{ ...s.row, ...s.bold, fontSize: 14, paddingTop: 4 }}>
          <span>TOTAL</span><span style={s.nums}>${total.toFixed(2)}</span>
        </div>
      </div>

      {/* Payment */}
      <div style={s.section}>
        <div style={s.row}><span>Payment</span><span style={{ textTransform: 'capitalize' }}>{txn.paymentMethod?.replace('_', ' ') ?? 'N/A'}</span></div>
        {tendered !== null && (
          <div style={s.row}><span>Tendered</span><span style={s.nums}>${tendered.toFixed(2)}</span></div>
        )}
        {change !== null && change > 0 && (
          <div style={{ ...s.row, ...s.bold }}><span>Change</span><span style={s.nums}>${change.toFixed(2)}</span></div>
        )}
      </div>

      {/* Barcode */}
      <div style={{ display: 'flex', justifyContent: 'center', padding: '12px 0' }}>
        <svg ref={barcodeRef} />
      </div>

      {/* Footer */}
      {(config?.footer || footerText) && (
        <div style={{ ...s.center, ...s.light, paddingBottom: 4 }}>{config?.footer || footerText}</div>
      )}
      {config?.returnPolicy && (
        <div style={{ ...s.center, color: '#aaa', fontSize: 10, paddingBottom: 4 }}>{config.returnPolicy}</div>
      )}
      {config?.social && (
        <div style={{ ...s.center, ...s.light, paddingBottom: 8 }}>{config.social}</div>
      )}
    </div>
  )
}

function FullPageReceipt({ data, config, footerText }: { data: POSReceiptProps['data']; config?: ReceiptConfig; footerText?: string }) {
  const barcodeRef = useRef<SVGSVGElement>(null)
  const logoSrc = useStoreLogo()
  const { txn, company, location, date, subtotal, discountTotal, taxTotal, total, rounding, tendered, change, addr, phone, email } = useReceiptData(data)
  useBarcode(barcodeRef, txn.transactionNumber, { width: 2, height: 50, fontSize: 12 })

  const f = (n: number) => `$${n.toFixed(2)}`

  return (
    <div style={{
      background: '#fff', color: '#000', fontFamily: 'Helvetica, Arial, sans-serif',
      width: '100%', maxWidth: 600, margin: '0 auto', fontSize: 13, lineHeight: '1.5',
    }}>
      {/* Header — company left, transaction right */}
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', paddingBottom: 16 }}>
        <div>
          {logoSrc ? (
            <img src={logoSrc} alt={company.name} style={{ maxHeight: 56, maxWidth: 200, objectFit: 'contain', marginBottom: 4 }} />
          ) : (
            <div style={{ fontSize: 20, fontWeight: 'bold' }}>{company.name}</div>
          )}
          {location.name !== company.name && <div style={{ color: '#555', fontSize: 12 }}>{location.name}</div>}
          {addr?.street && <div style={{ fontSize: 12 }}>{addr.street}</div>}
          {(addr?.city || addr?.state || addr?.zip) && (
            <div style={{ fontSize: 12 }}>{[addr?.city, addr?.state].filter(Boolean).join(', ')} {addr?.zip}</div>
          )}
          {phone && <div style={{ fontSize: 12 }}>{phone}</div>}
          {email && <div style={{ fontSize: 12 }}>{email}</div>}
          {config?.header && <div style={{ fontSize: 12, color: '#555', marginTop: 2 }}>{config.header}</div>}
        </div>
        <div style={{ textAlign: 'right' }}>
          <div style={{ fontSize: 16, fontWeight: 'bold' }}>{txn.transactionNumber}</div>
          <div style={{ fontSize: 12, color: '#555', textTransform: 'capitalize' }}>{txn.transactionType.replace('_', ' ')}</div>
          <div style={{ fontSize: 12, color: '#555' }}>{date.toLocaleDateString()}</div>
          <div style={{ fontSize: 12, color: '#555' }}>{date.toLocaleTimeString()}</div>
        </div>
      </div>

      {/* Divider */}
      <div style={{ borderBottom: '1px solid #ddd', marginBottom: 16 }} />

      {/* Line items table */}
      <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13 }}>
        <thead>
          <tr style={{ background: '#f5f5f5' }}>
            <th style={{ textAlign: 'left', padding: '6px 8px', fontWeight: 600, fontSize: 11, textTransform: 'uppercase', color: '#555' }}>Item</th>
            <th style={{ textAlign: 'right', padding: '6px 8px', fontWeight: 600, fontSize: 11, textTransform: 'uppercase', color: '#555', width: 50 }}>Qty</th>
            <th style={{ textAlign: 'right', padding: '6px 8px', fontWeight: 600, fontSize: 11, textTransform: 'uppercase', color: '#555', width: 80 }}>Price</th>
            <th style={{ textAlign: 'right', padding: '6px 8px', fontWeight: 600, fontSize: 11, textTransform: 'uppercase', color: '#555', width: 80 }}>Total</th>
          </tr>
        </thead>
        <tbody>
          {txn.lineItems.map((item, i) => (
            <tr key={i} style={{ borderBottom: '1px solid #eee' }}>
              <td style={{ padding: '6px 8px' }}>
                {item.description}
                {parseFloat(item.discountAmount ?? '0') > 0 && (
                  <div style={{ fontSize: 11, color: '#999' }}>Discount: -{f(parseFloat(item.discountAmount!))}</div>
                )}
              </td>
              <td style={{ padding: '6px 8px', textAlign: 'right', fontVariantNumeric: 'tabular-nums' }}>{item.qty}</td>
              <td style={{ padding: '6px 8px', textAlign: 'right', fontVariantNumeric: 'tabular-nums' }}>{f(parseFloat(item.unitPrice))}</td>
              <td style={{ padding: '6px 8px', textAlign: 'right', fontVariantNumeric: 'tabular-nums' }}>{f(parseFloat(item.lineTotal))}</td>
            </tr>
          ))}
        </tbody>
      </table>

      {/* Totals — right aligned */}
      <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: 12 }}>
        <div style={{ width: 220 }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', padding: '3px 0' }}>
            <span>Subtotal</span><span style={{ fontVariantNumeric: 'tabular-nums' }}>{f(subtotal)}</span>
          </div>
          {discountTotal > 0 && (
            <div style={{ display: 'flex', justifyContent: 'space-between', padding: '3px 0', color: '#555' }}>
              <span>Discount</span><span style={{ fontVariantNumeric: 'tabular-nums' }}>-{f(discountTotal)}</span>
            </div>
          )}
          <div style={{ display: 'flex', justifyContent: 'space-between', padding: '3px 0' }}>
            <span>Tax</span><span style={{ fontVariantNumeric: 'tabular-nums' }}>{f(taxTotal)}</span>
          </div>
          {rounding !== 0 && (
            <div style={{ display: 'flex', justifyContent: 'space-between', padding: '3px 0', color: '#888', fontSize: 12 }}>
              <span>Rounding</span><span style={{ fontVariantNumeric: 'tabular-nums' }}>{rounding > 0 ? '+' : ''}{rounding.toFixed(2)}</span>
            </div>
          )}
          <div style={{ borderTop: '1px solid #ddd', marginTop: 4, paddingTop: 6, display: 'flex', justifyContent: 'space-between', fontWeight: 'bold', fontSize: 16 }}>
            <span>Total</span><span style={{ fontVariantNumeric: 'tabular-nums' }}>{f(total)}</span>
          </div>
        </div>
      </div>

      {/* Payment info */}
      <div style={{ marginTop: 16, padding: '12px 0', borderTop: '1px solid #ddd' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between' }}>
          <span>Payment Method</span>
          <span style={{ textTransform: 'capitalize', fontWeight: 500 }}>{txn.paymentMethod?.replace('_', ' ') ?? 'N/A'}</span>
        </div>
        {tendered !== null && (
          <div style={{ display: 'flex', justifyContent: 'space-between', color: '#555', fontSize: 12, marginTop: 2 }}>
            <span>Tendered</span><span style={{ fontVariantNumeric: 'tabular-nums' }}>{f(tendered)}</span>
          </div>
        )}
        {change !== null && change > 0 && (
          <div style={{ display: 'flex', justifyContent: 'space-between', fontWeight: 'bold', marginTop: 2 }}>
            <span>Change</span><span style={{ fontVariantNumeric: 'tabular-nums' }}>{f(change)}</span>
          </div>
        )}
      </div>

      {/* Barcode */}
      <div style={{ display: 'flex', justifyContent: 'center', padding: '16px 0' }}>
        <svg ref={barcodeRef} />
      </div>

      {/* Footer */}
      <div style={{ borderTop: '1px solid #eee', paddingTop: 12, textAlign: 'center', fontSize: 11, color: '#999' }}>
        {(config?.footer || footerText) && <div>{config?.footer || footerText}</div>}
        {config?.returnPolicy && <div style={{ marginTop: 4 }}>{config.returnPolicy}</div>}
        {config?.social && <div style={{ marginTop: 4 }}>{config.social}</div>}
      </div>
    </div>
  )
}

export function printReceipt() {
  const el = document.getElementById('pos-receipt-print')
  if (!el) return

  // Clone the receipt into an iframe for clean printing
  const iframe = document.createElement('iframe')
  iframe.style.cssText = 'position:fixed;left:-9999px;width:400px;height:800px;border:none;'
  document.body.appendChild(iframe)

  const doc = iframe.contentDocument
  if (!doc) { document.body.removeChild(iframe); return }

  doc.open()
  doc.write(`<!DOCTYPE html><html><head><style>body{margin:0;padding:8px;background:#fff;}</style></head><body>${el.innerHTML}</body></html>`)
  doc.close()

  // Wait for content to render then print
  setTimeout(() => {
    try {
      iframe.contentWindow?.focus()
      iframe.contentWindow?.print()
    } catch {
      // Fallback: just use window.print
      window.print()
    }
    setTimeout(() => document.body.removeChild(iframe), 2000)
  }, 300)
}

export async function downloadReceiptPDF(txnNumber?: string, format: 'thermal' | 'full' = 'thermal') {
  const el = document.getElementById('pos-receipt-print')
  if (!el) return

  const html2pdf = (await import('html2pdf.js')).default

  if (format === 'full') {
    html2pdf()
      .set({
        margin: [10, 10, 10, 10],
        filename: `receipt-${txnNumber ?? 'unknown'}.pdf`,
        image: { type: 'jpeg', quality: 0.95 },
        html2canvas: { scale: 2, useCORS: true },
        jsPDF: { unit: 'mm', format: 'letter', orientation: 'portrait' },
      })
      .from(el)
      .save()
  } else {
    // Thermal — dynamic height based on content
    const heightPx = el.scrollHeight + 16
    const heightMm = Math.ceil(heightPx * 0.265) + 8
    html2pdf()
      .set({
        margin: [2, 2, 2, 2],
        filename: `receipt-${txnNumber ?? 'unknown'}.pdf`,
        image: { type: 'jpeg', quality: 0.95 },
        html2canvas: { scale: 2, useCORS: true, width: 280 },
        jsPDF: { unit: 'mm', format: [72, heightMm], orientation: 'portrait' },
      })
      .from(el)
      .save()
  }
}
