/**
 * Canonical ProposalContent types — wave-11 leaf-C.
 * Owned by: proposal-editor (spec).
 * Consumed by: public-proposal-view (zync-www renderer), proposal-editor UI, @zync/ui ProposalRenderer.
 *
 * Currency: ISO 4217 (ILS | USD | EUR etc.); amounts are base currency units (not subunits).
 */

import { z } from 'zod'

export interface LineItem {
  id: string
  description: string
  quantity: number
  unit_price: number
  tax_pct: number       // 0 | 17 | other
  product_id?: string   // omitted for freeform items
}

export type ProposalSection =
  | { type: 'text';         id: string; html: string }
  | { type: 'line_items';   id: string; items: LineItem[] }
  | { type: 'image';        id: string; url: string; alt: string; align: 'start' | 'center' | 'end' }
  | { type: 'divider';      id: string; label?: string }
  | { type: 'testimonials'; id: string; items: { quote: string; author: string; company: string }[] }
  | { type: 'team';         id: string; members: { user_id: string; role_label: string }[] }

export interface ProposalContent {
  sections: ProposalSection[]
  settings: {
    show_line_tax: boolean
    show_subtotal: boolean
    discount_pct: number  // 0–100
    currency: string      // ISO 4217, default from tenant default_currency
  }
}

// ── Zod schemas ────────────────────────────────────────────────────────────────

export const lineItemSchema: z.ZodType<LineItem> = z.object({
  id: z.string().min(1),
  description: z.string().min(1),
  quantity: z.number().positive(),
  unit_price: z.number().min(0),
  tax_pct: z.number().min(0),
  product_id: z.string().uuid().optional(),
})

export const proposalSectionSchema: z.ZodType<ProposalSection> = z.discriminatedUnion('type', [
  z.object({ type: z.literal('text'), id: z.string(), html: z.string() }),
  z.object({ type: z.literal('line_items'), id: z.string(), items: z.array(lineItemSchema) }),
  z.object({
    type: z.literal('image'),
    id: z.string(),
    url: z.string().min(1),
    alt: z.string(),
    align: z.enum(['start', 'center', 'end']),
  }),
  z.object({ type: z.literal('divider'), id: z.string(), label: z.string().optional() }),
  z.object({
    type: z.literal('testimonials'),
    id: z.string(),
    items: z.array(z.object({ quote: z.string(), author: z.string(), company: z.string() })),
  }),
  z.object({
    type: z.literal('team'),
    id: z.string(),
    members: z.array(z.object({ user_id: z.string().uuid(), role_label: z.string() })),
  }),
])

const proposalContentSettingsSchema = z.object({
  show_line_tax: z.boolean(),
  show_subtotal: z.boolean(),
  discount_pct: z.number().min(0).max(100),
  currency: z.string().regex(/^[A-Z]{3}$/),
})

export const proposalContentSchema: z.ZodType<ProposalContent> = z.object({
  sections: z.array(proposalSectionSchema),
  settings: proposalContentSettingsSchema,
})

export const createProposalSchema = z.object({
  customer_id: z.string().uuid().optional(),
  subject: z.string().min(1).max(500),    // maps to proposals.name
  content: proposalContentSchema,
  expires_at: z.string().datetime().optional(),
})

export const updateProposalSchema = z.object({
  subject: z.string().min(1).max(500).optional(),
  content: proposalContentSchema.optional(),
  expires_at: z.string().datetime().optional(),
})

export const sendProposalSchema = z.object({
  to: z.array(z.string().email()).min(1),
  subject: z.string().optional(),
  message: z.string().optional(),
})

export const saveProposalTemplateSchema = z.object({
  proposal_id: z.string().uuid(),
  name: z.string().min(1).max(500),
})

// ── Total computation ─────────────────────────────────────────────────────────

/**
 * Compute the denormalized total_amount from ProposalContent.
 * For each line_items section: amount = quantity * unit_price; tax = amount * tax_pct / 100.
 * Sum (amount + tax) for all line items across all line_items sections.
 * Apply settings.discount_pct to grand total.
 * Returns value rounded to 2 decimal places.
 */
export function computeProposalTotal(content: ProposalContent): number {
  let subtotal = 0
  for (const section of content.sections) {
    if (section.type !== 'line_items') continue
    for (const item of section.items) {
      const amount = item.quantity * item.unit_price
      const tax = amount * (item.tax_pct / 100)
      subtotal += amount + tax
    }
  }
  const discount = content.settings.discount_pct / 100
  const total = subtotal * (1 - discount)
  return Math.round(total * 100) / 100
}

/**
 * Generate a URL-safe opaque token for a proposal's public link.
 * Uses crypto.randomUUID() (available in both Cloudflare Workers and Node 18+).
 */
export function generateProposalPublicToken(): string {
  return crypto.randomUUID().replace(/-/g, '')
}
