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

const root = process.cwd()
const outRoot = join(root, 'content_population_exports')
const intakePath = join(root, 'data', 'handoff', 'owner-response-intake.json')
mkdirSync(outRoot, { recursive: true })
mkdirSync(dirname(intakePath), { recursive: true })

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 (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 nonempty(value: any) { return String(value || '').trim().length > 0 }
function isoish(value: any) { const parsed = Date.parse(String(value || '').trim()); return Number.isFinite(parsed) }

const generatedAt = new Date().toISOString()
const ownerMessages = readJson(join(outRoot, 'owner_handoff_messages.json'), {})
const templateRows = (ownerMessages.messages || []).map((message: any) => ({
  lane: message.Lane,
  owner: message.Audience,
  messageSubject: message.Subject,
  messageSent: false,
  sentAt: '',
  sentVia: '',
  responseReceived: false,
  responseReceivedAt: '',
  responderName: '',
  responseSummary: '',
  evidenceFilesUpdated: [],
  commandRunAfterUpdate: '',
  gateResultAfterUpdate: 'not_run',
  notes: ''
}))

if (!existsSync(intakePath)) {
  writeJson(intakePath, {
    purpose: 'Editable intake tracker for owner replies to the JV handoff messages. This records communication/evidence receipt only; it does not approve content or bypass any gate.',
    guardrails: [
      'Only set responseReceived=true after the owner has replied with usable evidence or a concrete decision.',
      'Keep evidenceFilesUpdated limited to actual edited files or saved evidence artifacts.',
      'Run the lane command after updating evidence and record the result; do not mark gates passed manually.',
      'Do not store credentials or secrets in this tracker.'
    ],
    responses: templateRows
  })
}

const intake = readJson(intakePath, { responses: [] })
const rows = (ownerMessages.messages || []).map((message: any) => {
  const response = (intake.responses || []).find((row: any) => row.lane === message.Lane) || {}
  const sentOk = response.messageSent === true && isoish(response.sentAt) && nonempty(response.sentVia)
  const responseOk = response.responseReceived === true && isoish(response.responseReceivedAt) && nonempty(response.responderName) && nonempty(response.responseSummary)
  const evidenceOk = Array.isArray(response.evidenceFilesUpdated) && response.evidenceFilesUpdated.length > 0
  const commandOk = nonempty(response.commandRunAfterUpdate) && ['pass', 'blocked_with_new_evidence'].includes(String(response.gateResultAfterUpdate || ''))
  const status = responseOk && evidenceOk && commandOk ? 'ready_for_gate_rerun' : sentOk ? 'awaiting_response_or_evidence' : 'not_sent'
  const blockers = []
  if (!sentOk) blockers.push('message not recorded as sent')
  if (!responseOk) blockers.push('owner response not recorded')
  if (!evidenceOk) blockers.push('evidence files not updated')
  if (!commandOk) blockers.push('post-update command result not recorded')
  return {
    Lane: message.Lane,
    Owner: message.Audience,
    Status: status,
    MessageSent: sentOk ? 'yes' : 'no',
    ResponseReceived: responseOk ? 'yes' : 'no',
    EvidenceUpdated: evidenceOk ? 'yes' : 'no',
    CommandResultRecorded: commandOk ? 'yes' : 'no',
    EvidenceFilesUpdated: response.evidenceFilesUpdated || [],
    NextAction: blockers.length ? blockers.join('; ') : 'Run the lane regeneration command and master verifier.',
    Guardrail: message.Guardrail
  }
})

const readyRows = rows.filter(row => row.Status === 'ready_for_gate_rerun')
const manifest = {
  generatedAt,
  ready: rows.length > 0 && readyRows.length === rows.length,
  purpose: 'Validates whether owner handoff messages have been sent and whether usable owner responses/evidence updates have been recorded before rerunning blocker gates.',
  intakeFile: 'data/handoff/owner-response-intake.json',
  counts: {
    lanes: rows.length,
    readyForGateRerun: readyRows.length,
    awaitingResponseOrEvidence: rows.filter(row => row.Status === 'awaiting_response_or_evidence').length,
    notSent: rows.filter(row => row.Status === 'not_sent').length
  },
  rows,
  files: {
    markdown: 'content_population_exports/owner_response_intake.md',
    json: 'content_population_exports/owner_response_intake.json',
    csv: 'content_population_exports/owner_response_intake.csv',
    editableIntake: 'data/handoff/owner-response-intake.json'
  }
}

writeJson(join(outRoot, 'owner_response_intake.json'), manifest)
writeFileSync(join(outRoot, 'owner_response_intake.csv'), csv(rows, ['Lane', 'Owner', 'Status', 'MessageSent', 'ResponseReceived', 'EvidenceUpdated', 'CommandResultRecorded', 'EvidenceFilesUpdated', 'NextAction', 'Guardrail']), 'utf8')
writeFileSync(join(outRoot, 'owner_response_intake.md'), [
  '# Owner response intake',
  '',
  `Generated: ${generatedAt}`,
  '',
  `Ready for gate reruns: **${manifest.ready ? 'YES' : 'NO'}**`,
  `Lanes ready: ${manifest.counts.readyForGateRerun}/${manifest.counts.lanes}`,
  `Awaiting response/evidence: ${manifest.counts.awaitingResponseOrEvidence}`,
  `Not sent: ${manifest.counts.notSent}`,
  '',
  `Editable tracker: \`${manifest.intakeFile}\``,
  '',
  'This tracker records owner communications and received evidence. It does not approve products, approve blank clinical claims, create staging evidence, or unlock paid provider calls by itself.',
  '',
  '## Rows',
  '| Lane | Owner | Status | Next action |',
  '|---|---|---|---|',
  ...rows.map(row => `| ${row.Lane} | ${row.Owner} | ${row.Status} | ${row.NextAction.replace(/\|/g, '/')} |`),
  '',
  '## Guardrail',
  'After an owner response is recorded, rerun the lane-specific validation command. The authoritative gate remains the generated validator output, not this communication tracker.',
  ''
].join('\n'), 'utf8')

console.log(`Owner response intake ready: ${manifest.ready}`)
console.log(`Lanes ready: ${manifest.counts.readyForGateRerun}/${manifest.counts.lanes}`)
console.log(`Not sent: ${manifest.counts.notSent}`)
if (!manifest.ready) process.exitCode = 1
