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

const root = process.cwd()
const outRoot = join(root, 'content_population_exports')
mkdirSync(outRoot, { recursive: true })

function parseCsv(text: string) {
  const rows: string[][] = []
  let row: string[] = []
  let cell = ''
  let quoted = false
  for (let i = 0; i < text.length; i++) {
    const ch = text[i]
    const next = text[i + 1]
    if (quoted) {
      if (ch === '"' && next === '"') {
        cell += '"'
        i++
      } else if (ch === '"') {
        quoted = false
      } else {
        cell += ch
      }
    } else if (ch === '"') {
      quoted = true
    } else if (ch === ',') {
      row.push(cell)
      cell = ''
    } else if (ch === '\n') {
      row.push(cell.replace(/\r$/, ''))
      rows.push(row)
      row = []
      cell = ''
    } else {
      cell += ch
    }
  }
  if (cell || row.length) {
    row.push(cell.replace(/\r$/, ''))
    rows.push(row)
  }
  const headers = rows.shift() || []
  return rows
    .filter(values => values.some(value => value !== ''))
    .map(values => Object.fromEntries(headers.map((header, index) => [header, values[index] || ''])))
}

function csv(rows: any[], headers: string[]) {
  const esc = (value: any) => {
    if (value === undefined || value === null) value = ''
    if (Array.isArray(value)) value = value.join(' | ')
    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 readCsv(path: string) {
  if (!existsSync(path)) return []
  return parseCsv(readFileSync(path, 'utf8').replace(/^\uFEFF/, ''))
}

const generatedAt = new Date().toISOString()
const asinMapPath = join(root, 'data', 'sources', 'dataforseo', 'asin-map.csv')
const candidatePath = join(root, 'data', 'sources', 'dataforseo', 'products_raw', 'all-asin-candidates-from-dataforseo.csv')
const asinMap = readCsv(asinMapPath)
const candidates = readCsv(candidatePath)
const unresolvedTargets = asinMap.filter((row: any) => !String(row.ASIN || '').trim())
const rows = unresolvedTargets.map((target: any) => {
  const skuCandidates = candidates
    .filter((row: any) => row.SKU === target.SKU)
    .sort((a: any, b: any) => Number(b.CandidateScore || 0) - Number(a.CandidateScore || 0) || Number(a.Rank || 999) - Number(b.Rank || 999))
  const brandExact = skuCandidates.filter((row: any) => row.BrandExact === 'yes')
  const exactMatch = skuCandidates.filter((row: any) => row.ExactMatch === 'yes')
  const top = skuCandidates[0] || {}
  const topRejectedBecause = !top.ASIN
    ? 'no DataForSEO product candidates were returned'
    : top.BrandExact !== 'yes'
      ? 'top candidate is not a Just Vitamins brand/title match'
      : top.ExactMatch !== 'yes'
        ? 'top candidate does not match the target product strongly enough'
        : 'requires manual Amazon-page confirmation before promotion'
  return {
    SKU: target.SKU,
    Product: target.Product,
    CurrentStatus: target.Status || 'needs_asin',
    CandidateRows: skuCandidates.length,
    BrandExactRows: brandExact.length,
    ExactMatchRows: exactMatch.length,
    TopCandidateASIN: top.ASIN || '',
    TopCandidateScore: top.CandidateScore || '',
    TopCandidateBrandExact: top.BrandExact || '',
    TopCandidateExactMatch: top.ExactMatch || '',
    TopCandidateTitle: top.Title || '',
    TopCandidateUrl: top.Url || '',
    Decision: exactMatch.length > 0 ? 'manual_confirm_before_promotion' : 'keep_out_of_paid_payload',
    Evidence: topRejectedBecause
  }
})

const readyForManualConfirmation = rows.filter(row => row.Decision === 'manual_confirm_before_promotion').length
const keepOut = rows.filter(row => row.Decision === 'keep_out_of_paid_payload').length
const manifest = {
  generatedAt,
  ready: true,
  recommendation: keepOut > 0
    ? 'Do not guess unresolved ASINs. Keep these SKUs outside the paid DataForSEO Reviews payload unless a later Amazon-page confirmation proves an exact Just Vitamins match.'
    : 'Exact-match candidates exist but still require manual Amazon-page confirmation before promotion.',
  counts: {
    unresolvedTargets: rows.length,
    candidateRows: rows.reduce((sum, row) => sum + Number(row.CandidateRows || 0), 0),
    brandExactRows: rows.reduce((sum, row) => sum + Number(row.BrandExactRows || 0), 0),
    exactMatchRows: rows.reduce((sum, row) => sum + Number(row.ExactMatchRows || 0), 0),
    readyForManualConfirmation,
    keepOutOfPaidPayload: keepOut
  },
  files: {
    asinMap: 'data/sources/dataforseo/asin-map.csv',
    dataforseoCandidates: 'data/sources/dataforseo/products_raw/all-asin-candidates-from-dataforseo.csv',
    reportMd: 'content_population_exports/dataforseo_unresolved_asin_evidence.md',
    reportCsv: 'content_population_exports/dataforseo_unresolved_asin_evidence.csv',
    reportJson: 'content_population_exports/dataforseo_unresolved_asin_evidence.json'
  },
  unresolvedTargets: rows
}

writeFileSync(join(outRoot, 'dataforseo_unresolved_asin_evidence.json'), JSON.stringify(manifest, null, 2) + '\n', 'utf8')
writeFileSync(join(outRoot, 'dataforseo_unresolved_asin_evidence.csv'), csv(rows, [
  'SKU',
  'Product',
  'CurrentStatus',
  'CandidateRows',
  'BrandExactRows',
  'ExactMatchRows',
  'TopCandidateASIN',
  'TopCandidateScore',
  'TopCandidateBrandExact',
  'TopCandidateExactMatch',
  'TopCandidateTitle',
  'TopCandidateUrl',
  'Decision',
  'Evidence'
]), 'utf8')
writeFileSync(join(outRoot, 'dataforseo_unresolved_asin_evidence.md'), [
  '# DataForSEO unresolved ASIN evidence',
  '',
  `Generated: ${generatedAt}`,
  '',
  manifest.recommendation,
  '',
  `Unresolved targets: ${manifest.counts.unresolvedTargets}`,
  `DataForSEO candidate rows inspected: ${manifest.counts.candidateRows}`,
  `Brand-exact rows: ${manifest.counts.brandExactRows}`,
  `Exact-match rows: ${manifest.counts.exactMatchRows}`,
  `Keep out of paid payload: ${manifest.counts.keepOutOfPaidPayload}`,
  '',
  '## Targets',
  ...rows.map(row => [
    `### ${row.SKU} — ${row.Product}`,
    `- Decision: ${row.Decision}`,
    `- Evidence: ${row.Evidence}`,
    `- Candidate rows: ${row.CandidateRows}; brand-exact: ${row.BrandExactRows}; exact-match: ${row.ExactMatchRows}`,
    `- Top candidate: ${row.TopCandidateASIN || 'none'} — ${row.TopCandidateTitle || 'none'}`,
    ''
  ].join('\n')),
  '## Guardrail',
  'These rows are evidence for *not* guessing. They do not promote ASINs and they do not unlock provider spend.',
  ''
].join('\n'), 'utf8')

console.log(`DataForSEO unresolved ASIN evidence ready: ${manifest.ready}`)
console.log(`Unresolved targets: ${manifest.counts.unresolvedTargets}`)
console.log(`Keep out of paid payload: ${manifest.counts.keepOutOfPaidPayload}`)
