#!/usr/bin/env bun
// Emit Matrixify-format CSVs for the 4 new metaobject definition groups
// produced by generate-pilot-content.ts:
//   - scientific_study
//   - timeline_phase  +  timeline_block (with phases as list.metaobject_reference)
//   - comparison_column + comparison_row + comparison_table
//   - faq_pair + faq_block
//
// Output: content_population_exports/pilot-extended-<definition>.csv
// One CSV per definition, long format (one row per Handle x Field x Value).
//
// Usage: bun scripts/export-extended-metaobjects.ts

import { readdirSync, readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs'
import { join } from 'path'

const ROOT = join(import.meta.dir, '..')
const IN_DIR = join(ROOT, 'data', 'content', 'pilot-extended')
const OUT_DIR = join(ROOT, 'content_population_exports')

const META_COLS = ['Handle', 'Display Name', 'Status', 'Definition: Handle', 'Definition: Name', 'Field', 'Value'] as const

const DEFINITIONS = {
  scientific_study: 'Scientific Study',
  timeline_phase: 'Timeline Phase',
  timeline_block: 'Timeline Block (Results)',
  comparison_column: 'Comparison Column',
  comparison_row: 'Comparison Row',
  comparison_table: 'Comparison Table',
  faq_pair: 'FAQ Pair',
  faq_block: 'FAQ Block'
} as const

type DefKey = keyof typeof DEFINITIONS

function csvEscape(v: unknown): string {
  if (Array.isArray(v)) v = v.join(', ')
  if (v === undefined || v === null) v = ''
  const s = String(v)
  return /[",\n\r]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s
}

function toCsv(rows: (string | number | boolean | null | undefined)[][]): string {
  return rows.map(r => r.map(csvEscape).join(',')).join('\n') + '\n'
}

type RowBuckets = Record<DefKey, (string | number | boolean | null | undefined)[][]>

function newBuckets(): RowBuckets {
  return Object.fromEntries(
    (Object.keys(DEFINITIONS) as DefKey[]).map(k => [k, [META_COLS as unknown as string[]]])
  ) as RowBuckets
}

function addField(
  buckets: RowBuckets,
  def: DefKey,
  handle: string,
  displayName: string,
  status: string,
  field: string,
  value: unknown
) {
  buckets[def].push([handle, displayName, status, def, DEFINITIONS[def], field, value as any])
}

function emitScientificStudy(buckets: RowBuckets, ss: any) {
  if (!ss?.handle) return
  const def: DefKey = 'scientific_study'
  const h = ss.handle, n = ss.name_internal || ss.headline || h, st = ss.status || 'draft'
  addField(buckets, def, h, n, st, 'name_internal', ss.name_internal || '')
  addField(buckets, def, h, n, st, 'headline', ss.headline || '')
  addField(buckets, def, h, n, st, 'body_copy', ss.body_copy || '')
  addField(buckets, def, h, n, st, 'link_url', ss.link_url || '')
  addField(buckets, def, h, n, st, 'link_label', ss.link_label || '')
  const stats = (ss.stats as any[]) || []
  for (let i = 0; i < 3; i++) {
    const s = stats[i] || {}
    addField(buckets, def, h, n, st, `stat_${i + 1}_value`, s.value ?? '')
    addField(buckets, def, h, n, st, `stat_${i + 1}_label`, s.label ?? '')
  }
  addField(buckets, def, h, n, st, 'image', ss.image || '')
}

function emitTimeline(buckets: RowBuckets, tb: any) {
  if (!tb?.handle) return
  const def: DefKey = 'timeline_block'
  const h = tb.handle, n = tb.name_internal || h, st = tb.status || 'draft'
  addField(buckets, def, h, n, st, 'headline', tb.headline || '')
  addField(buckets, def, h, n, st, 'subtitle', tb.subtitle || '')
  addField(buckets, def, h, n, st, 'intro_copy', tb.intro_copy || '')
  addField(buckets, def, h, n, st, 'study_link_label', tb.study_link_label || '')
  addField(buckets, def, h, n, st, 'study_link_url', tb.study_link_url || '')

  const phases = (tb.phases as any[]) || []
  const phaseRefs = phases.map(p => `timeline_phase.${p.handle}`).join(', ')
  addField(buckets, def, h, n, st, 'phases', phaseRefs)

  // phase entries on their own sheet
  const pdef: DefKey = 'timeline_phase'
  for (const p of phases) {
    const ph = p.handle, pn = p.phase_label || ph, pst = p.status || 'draft'
    addField(buckets, pdef, ph, pn, pst, 'phase_label', p.phase_label || '')
    addField(buckets, pdef, ph, pn, pst, 'body_copy', p.body_copy || '')
  }
}

function emitComparison(buckets: RowBuckets, ct: any) {
  if (!ct?.handle) return
  const tdef: DefKey = 'comparison_table'
  const h = ct.handle, n = ct.name_internal || h, st = ct.status || 'draft'
  addField(buckets, tdef, h, n, st, 'section_title', ct.section_title || '')
  addField(buckets, tdef, h, n, st, 'subtitle', ct.subtitle || '')
  const cols = (ct.columns as any[]) || []
  const rows = (ct.rows as any[]) || []
  addField(buckets, tdef, h, n, st, 'columns', cols.map(c => `comparison_column.${c.handle}`).join(', '))
  addField(buckets, tdef, h, n, st, 'rows', rows.map(r => `comparison_row.${r.handle}`).join(', '))

  const cdef: DefKey = 'comparison_column'
  for (const c of cols) {
    const ch = c.handle, cn = c.name || ch
    addField(buckets, cdef, ch, cn, 'draft', 'name', c.name || '')
    addField(buckets, cdef, ch, cn, 'draft', 'is_us', c.is_us ? 'true' : 'false')
    addField(buckets, cdef, ch, cn, 'draft', 'accent_colour', c.accent_colour || '')
    addField(buckets, cdef, ch, cn, 'draft', 'image', c.image || '')
  }

  const rdef: DefKey = 'comparison_row'
  for (const r of rows) {
    const rh = r.handle, rn = r.feature_label || rh, rst = r.status || 'draft'
    addField(buckets, rdef, rh, rn, rst, 'feature_label', r.feature_label || '')
    addField(buckets, rdef, rh, rn, rst, 'values_json', JSON.stringify(r.values || {}))
  }
}

function emitFaq(buckets: RowBuckets, fb: any) {
  if (!fb?.handle) return
  const bdef: DefKey = 'faq_block'
  const h = fb.handle, n = fb.name_internal || h, st = fb.status || 'draft'
  addField(buckets, bdef, h, n, st, 'section_title', fb.section_title || '')
  addField(buckets, bdef, h, n, st, 'cta_label', fb.cta_label || '')
  addField(buckets, bdef, h, n, st, 'cta_url', fb.cta_url || '')

  const pairs = (fb.pairs as any[]) || []
  addField(buckets, bdef, h, n, st, 'pairs', pairs.map(p => `faq_pair.${p.handle}`).join(', '))

  const pdef: DefKey = 'faq_pair'
  for (const p of pairs) {
    const ph = p.handle, pn = p.question || ph, pst = p.status || 'draft'
    addField(buckets, pdef, ph, pn, pst, 'scope', p.scope || 'product')
    addField(buckets, pdef, ph, pn, pst, 'question', p.question || '')
    addField(buckets, pdef, ph, pn, pst, 'answer', p.answer || '')
    addField(buckets, pdef, ph, pn, pst, 'source_citation_id', p.source_citation_id || '')
  }
}

async function main() {
  if (!existsSync(IN_DIR)) {
    console.error(`Input dir missing: ${IN_DIR}. Run generate-pilot-content.ts first.`)
    process.exit(1)
  }
  mkdirSync(OUT_DIR, { recursive: true })
  const buckets = newBuckets()
  const files = readdirSync(IN_DIR).filter(f => f.endsWith('.json'))
  if (files.length === 0) {
    console.error(`No pilot-extended JSONs in ${IN_DIR}`); process.exit(1)
  }
  for (const f of files) {
    const doc = JSON.parse(readFileSync(join(IN_DIR, f), 'utf8'))
    emitScientificStudy(buckets, doc.scientificStudy)
    emitTimeline(buckets, doc.timelineBlock)
    emitComparison(buckets, doc.comparisonTable)
    emitFaq(buckets, doc.faqBlock)
  }

  const summary: Record<string, number> = {}
  for (const def of Object.keys(DEFINITIONS) as DefKey[]) {
    const out = toCsv(buckets[def])
    const rowCount = buckets[def].length - 1
    const fileName = `pilot-extended-${def}.csv`
    writeFileSync(join(OUT_DIR, fileName), out, 'utf8')
    summary[def] = rowCount
    console.log(`  ${fileName.padEnd(45)} ${rowCount} rows`)
  }

  const manifestPath = join(OUT_DIR, 'pilot-extended-manifest.json')
  writeFileSync(
    manifestPath,
    JSON.stringify(
      {
        generatedAt: new Date().toISOString(),
        source: 'data/content/pilot-extended/',
        skus: files.map(f => f.replace(/\.json$/, '')),
        definitions: summary,
        notes: [
          'Long-format Matrixify CSVs per metaobject definition.',
          'Import order must respect references: comparison_column + comparison_row + timeline_phase + faq_pair FIRST, then comparison_table + timeline_block + faq_block + scientific_study.',
          'Confirm with Lewis that the Shopify template supports list.metaobject_reference for timeline_block.phases, comparison_table.columns/rows, faq_block.pairs.'
        ]
      },
      null,
      2
    )
  )
  console.log(`\nManifest: ${manifestPath}`)
}

await main()
