#!/usr/bin/env bun
import { existsSync, readdirSync, readFileSync, writeFileSync } from 'fs'
import { join } from 'path'

const root = process.cwd()
const outRoot = join(root, 'content_population_exports')
const contentRoot = join(root, 'data', 'content')
const productRoot = join(contentRoot, 'products')
const workflowRoot = join(contentRoot, 'workflow')
const intelRoot = join(root, 'data', 'intelligence')

function readJson(path: string, fallback: any = null) {
  if (!existsSync(path)) return fallback
  return JSON.parse(readFileSync(path, 'utf8').replace(/^\uFEFF/, ''))
}
function writeJson(path: string, data: any) { writeFileSync(path, JSON.stringify(data, null, 2) + '\n', 'utf8') }
function csv(rows: any[], headers: string[]) {
  const esc = (value: any) => {
    if (Array.isArray(value)) value = value.join(' | ')
    if (value === undefined || value === null) value = ''
    value = String(value)
    return /[",\n\r]/.test(value) ? `"${value.replace(/"/g, '""')}"` : value
  }
  return [headers.join(','), ...rows.map(row => headers.map(header => esc(row[header])).join(','))].join('\n') + '\n'
}
function files(dir: string, suffix = '.json') {
  if (!existsSync(dir)) return []
  return readdirSync(dir).filter(file => file.endsWith(suffix))
}
function gate(name: string, ready: boolean, evidence: any, blocker: string) {
  return { name, status: ready ? 'pass' : 'blocked', ready, evidence, blocker: ready ? '' : blocker }
}

const products = files(productRoot).map(file => readJson(join(productRoot, file))).filter(Boolean)
const workflowFiles = files(workflowRoot).filter(file => file !== 'index.json')
const asset = readJson(join(outRoot, 'asset_manifest_validation.json'), {})
const handoff = readJson(join(outRoot, 'handoff_manifest.json'), {})
const template = readJson(join(outRoot, 'template_schema_validation.json'), {})
const sourceDrops = readJson(join(outRoot, 'source_drop_validation.json'), {})
const claims = readJson(join(outRoot, 'claims_library_validation.json'), {})
const sourceRequest = readJson(join(outRoot, 'source_request_manifest.json'), {})
const plannedImages = readJson(join(outRoot, 'planned_image_filenames.json'), {})
const meta = readJson(join(contentRoot, 'metaobjects.json'), { definitions: {} })
const collections = readJson(join(contentRoot, 'smart-collections.json'), { collections: [] })
const requiredIntel = ['review-aspects', 'strengths-weaknesses', 'conversion-blockers', 'improvements', 'image-audit', 'photo-brief', 'competitor-comparison', 'amazon-reviews', 'reddit-pulse', 'flavor-intelligence', 'audience-profile', 'claims-evidence']
const intelCoverage = requiredIntel.map(view => {
  const count = products.filter(product => existsSync(join(intelRoot, product.sku, `${view}.json`))).length
  return { view, count, missing: products.length - count }
})
const approvalCounts = products.reduce((acc: any, product: any) => {
  for (const lane of ['content', 'compliance', 'images', 'export']) {
    const value = product.approval?.[lane] || 'missing'
    acc[lane] = acc[lane] || {}
    acc[lane][value] = (acc[lane][value] || 0) + 1
  }
  return acc
}, {})
const promoCards = meta.definitions?.promo_card || []
const mappedCollections = (collections.collections || []).filter((row: any) => row.promoCard).length
const gates = [
  gate('catalogue_content_seeded', products.length === 190, { products: products.length }, 'Expected 190 product content records.'),
  gate('workflow_seeded', workflowFiles.length === products.length, { workflowFiles: workflowFiles.length, products: products.length }, 'Every product needs a workflow record.'),
  gate('template_schema', Boolean(template.ready), { checks: template.checks?.length || 0 }, 'Dashboard/migration CSV headers must match Lewis/Euan XLSX template.'),
  gate('handoff_ready', Boolean(handoff.readyForLewis), { blockers: handoff.counts?.blockers, blockedSkus: handoff.counts?.blockedSkus }, 'Handoff manifest still has blockers.'),
  gate('asset_filenames_assigned', (asset.missingReferenceCount || 0) === 0 && plannedImages.totalRows === products.length * 3, { missingReferenceCount: asset.missingReferenceCount, plannedImageRows: plannedImages.totalRows }, 'All product image filenames must be assigned.'),
  gate('asset_uploads_ready', Boolean(asset.ready), { requiredCount: asset.requiredCount, missingUploadCount: asset.missingUploadCount }, 'Referenced product/metaobject assets must exist in the asset root / Shopify Files.'),
  gate('source_drops_ready', Boolean(sourceDrops.ready), { issues: sourceDrops.issues?.length || 0 }, 'Amazon/Trustpilot/Reddit source drops are missing or invalid.'),
  gate('claims_library_ready', Boolean(claims.ready), { claimCount: claims.claimCount, issues: claims.issueCount }, 'Clinical claims library is missing or invalid.'),
  gate('source_request_pack_ready', Boolean(sourceRequest.counts?.sourceRequestItems), sourceRequest.counts || {}, 'Source request pack must exist for external blockers.'),
  gate('promo_cards_seeded', promoCards.length > 0 && mappedCollections === (collections.collections || []).length, { promoCards: promoCards.length, mappedCollections, collections: (collections.collections || []).length }, 'Collection promo-card candidates/mappings missing.'),
  gate('full_intelligence_coverage', intelCoverage.every(row => row.count === products.length), { coverage: intelCoverage }, 'All intelligence files must exist for every catalogue SKU.'),
  gate('human_approval_complete', products.every(product => product.approval?.content === 'approved' && product.approval?.compliance === 'approved' && product.approval?.images === 'ready' && product.approval?.export === 'ready'), approvalCounts, 'Approval lanes are not complete.'),
]
const ready = gates.every(item => item.ready)
const report = {
  generatedAt: new Date().toISOString(),
  ready,
  objective: 'jv-dashboard/CONTENT_POPULATION_PLAN.md',
  summary: {
    totalGates: gates.length,
    passing: gates.filter(item => item.ready).length,
    blocked: gates.filter(item => !item.ready).length,
    productCount: products.length,
    workflowCount: workflowFiles.length,
    exportBlockers: handoff.counts?.blockers ?? null,
    missingAssetUploads: asset.missingUploadCount ?? null,
    sourceDropIssues: sourceDrops.issues?.length ?? null,
    claimsIssues: claims.issueCount ?? null,
  },
  gates,
  nextActions: gates.filter(item => !item.ready).map(item => item.blocker)
}
writeJson(join(outRoot, 'content_population_readiness.json'), report)
writeFileSync(join(outRoot, 'content_population_readiness.csv'), csv(gates.map(item => ({ Gate: item.name, Status: item.status, Blocker: item.blocker, Evidence: JSON.stringify(item.evidence) })), ['Gate', 'Status', 'Blocker', 'Evidence']), 'utf8')
const md = [
  '# JV content population readiness audit',
  '',
  `Generated: ${report.generatedAt}`,
  '',
  `Overall ready: **${ready ? 'YES' : 'NO'}**`,
  '',
  '## Summary',
  `- Gates passing: ${report.summary.passing}/${report.summary.totalGates}`,
  `- Product records: ${report.summary.productCount}`,
  `- Workflow records: ${report.summary.workflowCount}`,
  `- Export blockers: ${report.summary.exportBlockers}`,
  `- Missing asset uploads/files: ${report.summary.missingAssetUploads}`,
  `- Source drop issues: ${report.summary.sourceDropIssues}`,
  `- Claims validation issues: ${report.summary.claimsIssues}`,
  '',
  '## Gates',
  ...gates.map(item => `- ${item.ready ? '[PASS]' : '[BLOCKED]'} ${item.name}${item.blocker ? ` — ${item.blocker}` : ''}`),
  '',
  '## Next actions',
  ...report.nextActions.map(action => `- ${action}`),
  ''
].join('\n')
writeFileSync(join(outRoot, 'content_population_readiness.md'), md, 'utf8')
console.log(`Content population ready: ${ready}`)
console.log(`Gates passing: ${report.summary.passing}/${report.summary.totalGates}`)
console.log(`Blocked gates: ${report.summary.blocked}`)
if (!ready) process.exitCode = 1
