/**
 * ProposalRenderer — shared read-only renderer for proposal content.
 * Used by: editor live-preview (zync-app) and public proposal view (zync-www).
 *
 * Renders all ProposalSection types: text | line_items | image | divider |
 * testimonials | team. Unknown types are silently skipped (forward-compat).
 *
 * Uses isomorphic-dompurify for SSR-safe sanitization (Node + browser).
 *
 * Spec: proposal-editor (wave-11 leaf-C, spec 130).
 */
import * as React from 'react'
import DOMPurify from 'isomorphic-dompurify'
import type { ProposalContent } from '@zync/types'

// ── Types ──────────────────────────────────────────────────────────────────────

export interface ProposalRendererProps {
  content: ProposalContent
  /** Compact mode for the editor side-panel preview */
  compact?: boolean
}

type AnySection = { type: string; id: string; [k: string]: unknown }

// ── DOMPurify config ──────────────────────────────────────────────────────────

const DOMPURIFY_CONFIG = {
  ALLOWED_TAGS: [
    'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
    'ul', 'ol', 'li', 'strong', 'em', 'u', 'br',
    'blockquote', 'hr', 'table', 'thead', 'tbody', 'tr', 'th', 'td',
    'span', 'div', 'a',
  ],
  ALLOWED_ATTR: ['href', 'target', 'rel'],
  FORCE_BODY: true,
}

// ── Sanitized HTML component ──────────────────────────────────────────────────

function SanitizedHtml({ html }: { html: string }) {
  const safe = DOMPurify.sanitize(html, DOMPURIFY_CONFIG)
  return (
    <div
      style={{ lineHeight: 1.7, color: 'var(--color-ink)' }}
      // eslint-disable-next-line react/no-danger
      dangerouslySetInnerHTML={{ __html: safe }}
    />
  )
}

// ── Currency formatter ────────────────────────────────────────────────────────

function fmtCurrency(n: number, currency: string): string {
  try {
    return new Intl.NumberFormat(undefined, { style: 'currency', currency }).format(n)
  } catch {
    return `${currency} ${n.toFixed(2)}`
  }
}

// ── Section renderers ─────────────────────────────────────────────────────────

function TextSection({ section }: { section: AnySection }) {
  const html = typeof section.html === 'string' ? section.html : ''
  return (
    <div data-proposal-section style={{ padding: '1.5rem', maxWidth: '48rem', marginInline: 'auto', width: '100%' }}>
      <SanitizedHtml html={html} />
    </div>
  )
}

function LineItemsSection({ section, currency }: { section: AnySection; currency: string }) {
  type LI = { id: string; description: string; quantity: number; unit_price: number; tax_pct: number }
  const items = (section.items as LI[]) ?? []
  const settings = section._settings as { show_line_tax?: boolean; show_subtotal?: boolean; discount_pct?: number } | undefined
  const showLineTax = settings?.show_line_tax !== false
  const showSubtotal = settings?.show_subtotal !== false
  const discountPct = settings?.discount_pct ?? 0

  const subtotal = items.reduce((acc, it) => acc + it.quantity * it.unit_price, 0)
  const taxTotal = items.reduce((acc, it) => acc + it.quantity * it.unit_price * (it.tax_pct / 100), 0)
  const discountAmt = subtotal * discountPct / 100
  const total = subtotal + taxTotal - discountAmt

  const lineItemGridColumns = showLineTax
    ? 'minmax(8rem, 2fr) minmax(3rem, auto) minmax(5rem, auto) minmax(3rem, auto) minmax(5rem, auto)'
    : 'minmax(8rem, 2fr) minmax(3rem, auto) minmax(5rem, auto) minmax(5rem, auto)'
  const lineItemHeaderStyle: React.CSSProperties = {
    padding: '8px 12px',
    color: 'var(--color-ink-muted)',
    fontWeight: 500,
  }
  const lineItemCellStyle: React.CSSProperties = { padding: '10px 12px' }

  return (
    <div data-proposal-section data-proposal-pricing style={{ padding: '1.5rem', maxWidth: '56rem', marginInline: 'auto', width: '100%' }}>
      <div style={{ overflowX: 'auto' }}>
        <div role="table" style={{ width: '100%', fontSize: 14 }}>
          <div role="rowgroup">
            <div
              role="row"
              style={{ display: 'grid', gridTemplateColumns: lineItemGridColumns, borderBlockEnd: '2px solid var(--color-border)' }}
            >
              <div role="columnheader" style={{ ...lineItemHeaderStyle, textAlign: 'start' }}>Item</div>
              <div role="columnheader" style={{ ...lineItemHeaderStyle, textAlign: 'end' }}>Qty</div>
              <div role="columnheader" style={{ ...lineItemHeaderStyle, textAlign: 'end' }}>Unit price</div>
              {showLineTax && <div role="columnheader" style={{ ...lineItemHeaderStyle, textAlign: 'end' }}>Tax</div>}
              <div role="columnheader" style={{ ...lineItemHeaderStyle, textAlign: 'end' }}>Total</div>
            </div>
          </div>
          <div role="rowgroup">
            {items.map((item) => {
              const lineTotal = item.quantity * item.unit_price * (1 + item.tax_pct / 100)
              return (
                <div
                  key={item.id}
                  role="row"
                  style={{ display: 'grid', gridTemplateColumns: lineItemGridColumns, borderBlockEnd: '1px solid var(--color-border)' }}
                >
                  <div role="cell" style={{ ...lineItemCellStyle, color: 'var(--color-ink)', fontWeight: 500 }}>{item.description}</div>
                  <div role="cell" style={{ ...lineItemCellStyle, textAlign: 'end', color: 'var(--color-ink-muted)' }}>{item.quantity}</div>
                  <div role="cell" style={{ ...lineItemCellStyle, textAlign: 'end', color: 'var(--color-ink-muted)' }}>{fmtCurrency(item.unit_price, currency)}</div>
                  {showLineTax && <div role="cell" style={{ ...lineItemCellStyle, textAlign: 'end', color: 'var(--color-ink-muted)' }}>{item.tax_pct}%</div>}
                  <div role="cell" style={{ ...lineItemCellStyle, textAlign: 'end', color: 'var(--color-ink)', fontWeight: 600 }}>{fmtCurrency(lineTotal, currency)}</div>
                </div>
              )
            })}
          </div>
        </div>
      </div>
      {/* Totals */}
      <div style={{ display: 'flex', flexDirection: 'column', gap: 4, alignItems: 'flex-end', paddingBlockStart: 12 }}>
        {showSubtotal && (
          <div style={{ display: 'flex', gap: 24, fontSize: 13, color: 'var(--color-ink-muted)' }}>
            <span>Subtotal</span>
            <span>{fmtCurrency(subtotal, currency)}</span>
          </div>
        )}
        {taxTotal > 0 && (
          <div style={{ display: 'flex', gap: 24, fontSize: 13, color: 'var(--color-ink-muted)' }}>
            <span>Tax</span>
            <span>{fmtCurrency(taxTotal, currency)}</span>
          </div>
        )}
        {discountPct > 0 && (
          <div style={{ display: 'flex', gap: 24, fontSize: 13, color: 'var(--color-ink-muted)' }}>
            <span>Discount ({discountPct}%)</span>
            <span>−{fmtCurrency(discountAmt, currency)}</span>
          </div>
        )}
        <div style={{ display: 'flex', gap: 24, fontWeight: 700, fontSize: 15, borderBlockStart: '1px solid var(--color-border)', paddingBlockStart: 8, marginBlockStart: 4 }}>
          <span>Total</span>
          <span>{fmtCurrency(total, currency)}</span>
        </div>
      </div>
    </div>
  )
}

function ImageSection({ section }: { section: AnySection }) {
  const url = typeof section.url === 'string' ? section.url : null
  const alt = typeof section.alt === 'string' ? section.alt : ''
  const align = section.align as 'left' | 'center' | 'right' | undefined
  const justifyMap: Record<string, string> = { left: 'flex-start', center: 'center', right: 'flex-end' }
  if (!url) return null
  return (
    <div data-proposal-section style={{ padding: '1rem 1.5rem', display: 'flex', justifyContent: justifyMap[align ?? 'center'] ?? 'center' }}>
      <img
        src={url}
        alt={alt}
        style={{ maxWidth: '100%', maxHeight: '32rem', objectFit: 'contain', borderRadius: 6 }}
        loading="lazy"
      />
    </div>
  )
}

function DividerSection({ section }: { section: AnySection }) {
  return (
    <div data-proposal-section style={{ padding: '1rem 1.5rem', maxWidth: '56rem', marginInline: 'auto', width: '100%' }}>
      <hr style={{ border: 'none', borderBlockStart: '1px solid var(--color-border)', margin: 0 }} />
      {typeof section.label === 'string' && section.label && (
        <p style={{ textAlign: 'center', color: 'var(--color-ink-muted)', fontSize: 13, marginBlockStart: 8 }}>
          {section.label}
        </p>
      )}
    </div>
  )
}

function TestimonialsSection({ section }: { section: AnySection }) {
  type T = { quote: string; author: string; company: string }
  const items = (section.items as T[]) ?? []
  return (
    <div data-proposal-section style={{ padding: '1.5rem', maxWidth: '56rem', marginInline: 'auto', width: '100%' }}>
      <div style={{ display: 'grid', gap: 16, gridTemplateColumns: 'repeat(auto-fill, minmax(260px, 1fr))' }}>
        {items.map((t, i) => (
          <blockquote
            key={i}
            style={{
              margin: 0, padding: '1.25rem',
              background: 'var(--color-surface-raised)',
              borderRadius: 8,
              borderInlineStart: '3px solid var(--color-brand, var(--color-accent))',
            }}
          >
            <p style={{ margin: '0 0 12px', lineHeight: 1.6, color: 'var(--color-ink)', fontStyle: 'italic' }}>
              &ldquo;{t.quote}&rdquo;
            </p>
            <footer style={{ fontSize: 13, color: 'var(--color-ink-muted)' }}>
              <strong style={{ color: 'var(--color-ink)' }}>{t.author}</strong>
              {t.company && <span>, {t.company}</span>}
            </footer>
          </blockquote>
        ))}
      </div>
    </div>
  )
}

function TeamSection({ section }: { section: AnySection }) {
  type M = { user_id: string; role_label: string; name?: string }
  const members = (section.members as M[]) ?? []
  return (
    <div data-proposal-section style={{ padding: '1.5rem', maxWidth: '56rem', marginInline: 'auto', width: '100%' }}>
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 12 }}>
        {members.map((m, i) => (
          <div
            key={i}
            style={{
              padding: '12px 16px',
              background: 'var(--color-surface-raised)',
              borderRadius: 8,
              border: '1px solid var(--color-border)',
              minWidth: 160,
            }}
          >
            <div style={{ fontWeight: 600, fontSize: 15, color: 'var(--color-ink)' }}>
              {m.name ?? m.user_id}
            </div>
            <div style={{ fontSize: 13, color: 'var(--color-ink-muted)', marginBlockStart: 4 }}>
              {m.role_label}
            </div>
          </div>
        ))}
      </div>
    </div>
  )
}

// ── Main renderer ─────────────────────────────────────────────────────────────

export function ProposalRenderer({ content, compact = false }: ProposalRendererProps) {
  const currency = content.settings.currency ?? 'USD'
  const discountPct = content.settings.discount_pct ?? 0

  return (
    <div
      style={{
        fontFamily: 'var(--font-sans, system-ui, sans-serif)',
        color: 'var(--color-ink)',
        fontSize: compact ? 13 : 15,
      }}
    >
      {(content.sections as AnySection[]).map((section) => {
        switch (section.type) {
          case 'text':
            return <TextSection key={section.id} section={section} />
          case 'line_items':
            return (
              <LineItemsSection
                key={section.id}
                section={{
                  ...section,
                  _settings: {
                    show_line_tax: content.settings.show_line_tax,
                    show_subtotal: content.settings.show_subtotal,
                    discount_pct: discountPct,
                  },
                }}
                currency={currency}
              />
            )
          case 'image':
            return <ImageSection key={section.id} section={section} />
          case 'divider':
            return <DividerSection key={section.id} section={section} />
          case 'testimonials':
            return <TestimonialsSection key={section.id} section={section} />
          case 'team':
            return <TeamSection key={section.id} section={section} />
          default:
            return null
        }
      })}
    </div>
  )
}
