import fs from 'node:fs'
import crypto from 'node:crypto'

const source='contracts/screens/kbx.screen-recipes.json'
const scenarioSource='contracts/testing/kbx.test-scenarios.json'
const data=JSON.parse(fs.readFileSync(source,'utf8'))
const scenarios=JSON.parse(fs.readFileSync(scenarioSource,'utf8'))
const scenarioById=new Map(scenarios.scenarios.map(scenario=>[scenario.id,scenario]))
const sha=crypto.createHash('sha256').update(fs.readFileSync(source)).digest('hex')
const scenarioSha=crypto.createHash('sha256').update(fs.readFileSync(scenarioSource)).digest('hex')
const byCode=Object.fromEntries(data.recipes.map(recipe=>[recipe.code,recipe]))

const verification=data.recipes.map(recipe=>{
  const canonical=recipe.canonicalScenarioIds.flatMap(id=>scenarioById.has(id)?[scenarioById.get(id)]:[])
  const kinds=[...new Set(canonical.map(item=>item.kind))].sort()
  const tags=[...new Set(canonical.flatMap(item=>item.tags??[]))].sort()
  const evidence=[...new Set(canonical.flatMap(item=>item.evidence??[]))].sort()
  const missingScenarioKinds=recipe.testProfile.requiredScenarioKinds.filter(item=>!kinds.includes(item))
  const missingTags=recipe.testProfile.requiredTags.filter(item=>!tags.includes(item))
  const missingEvidence=recipe.testProfile.requiredEvidence.filter(item=>!evidence.includes(item))
  return {
    code:recipe.code,
    type:recipe.type,
    canonicalScenarioIds:recipe.canonicalScenarioIds,
    scenarioKinds:kinds,
    tags,
    evidence,
    requiredChecks:recipe.testProfile.requiredChecks,
    missingScenarioKinds,
    missingTags,
    missingEvidence,
    complete:!missingScenarioKinds.length&&!missingTags.length&&!missingEvidence.length,
  }
})

fs.writeFileSync('generated/screen-recipe-manifest.json',JSON.stringify({schemaVersion:data.schemaVersion,contractVersion:data.contractVersion,sourceSha256:sha,recipes:data.recipes},null,2)+'\n')
fs.writeFileSync('generated/screen-recipe-verification-manifest.json',JSON.stringify({schemaVersion:1,recipeContractVersion:data.contractVersion,scenarioContractVersion:scenarios.contractVersion,recipeSourceSha256:sha,scenarioSourceSha256:scenarioSha,recipes:verification},null,2)+'\n')
const ts=`// generated from ${source}; do not edit.\n// SHA256: ${sha}\nimport type { KbxScreenRecipeDefinition } from '../screen'\n\nexport const kbxScreenRecipeContractVersion=${JSON.stringify(data.contractVersion)} as const\nexport const kbxScreenRecipeCatalog=${JSON.stringify(byCode,null,2)} as const satisfies Record<string,KbxScreenRecipeDefinition>\nexport const kbxScreenRecipeVerificationCatalog=${JSON.stringify(Object.fromEntries(verification.map(item=>[item.code,item])),null,2)} as const\n`
fs.writeFileSync('packages/kbx-contracts/src/generated/screenRecipeCatalog.ts',ts)
console.log(`screen recipe contracts generated: recipes=${data.recipes.length}, verification=${verification.filter(item=>item.complete).length}/${verification.length}`)
