#!/usr/bin/env node
import fs from 'node:fs/promises'
import path from 'node:path'
import { fileURLToPath } from 'node:url'

const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const repoRoot = path.resolve(__dirname, '..')
const sourcePath = path.join(
  repoRoot,
  'docs/generated/higher_dimensional_training_maps/phase6c_dedicated_family_package_validation_report.json',
)
const outputPath = path.join(
  repoRoot,
  'website/src/shared/generated/windows-package-validation-summary.json',
)

const FAMILY_LABELS = {
  magic120cell: 'Magic120Cell dedicated-family training map',
  magiccube5d: 'MagicCube5D dedicated-family training map',
}

function parseJson(content, label) {
  try {
    return JSON.parse(content)
  } catch (error) {
    throw new Error(`${label} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`)
  }
}

function assertString(value, label) {
  if (typeof value !== 'string' || value.trim().length === 0) {
    throw new Error(`${label} must be a non-empty string.`)
  }
  return value
}

function assertBoolean(value, label) {
  if (typeof value !== 'boolean') {
    throw new Error(`${label} must be a boolean.`)
  }
  return value
}

function normalizePrePackageEditorBuild(value) {
  if (value == null) {
    return null
  }

  if (typeof value !== 'object') {
    throw new Error('prePackageEditorBuild must be an object when present.')
  }

  const lane = assertString(value.lane, 'prePackageEditorBuild.lane')
  const performed = assertBoolean(value.performed, 'prePackageEditorBuild.performed')
  if (value.result !== 'passed' && value.result !== 'not-run') {
    throw new Error('prePackageEditorBuild.result must be "passed" or "not-run".')
  }

  return {
    lane,
    performed,
    result: value.result,
  }
}

function normalizeSmokeResult(value, label) {
  if (value === 'passed' || value === 'failed') {
    return value
  }
  throw new Error(`${label} must be "passed" or "failed".`)
}

function buildFallbackLabel(mapUrl) {
  const mapName = mapUrl.split('/').pop() || mapUrl
  return `${mapName} packaged smoke map`
}

function buildSummary(report) {
  const generatedAtUtc = assertString(report.generatedAtUtc, 'generatedAtUtc')
  const configuration = assertString(report.configuration, 'configuration')
  const skipBuild = assertBoolean(report.skipBuild, 'skipBuild')
  const prePackageEditorBuild = normalizePrePackageEditorBuild(report.prePackageEditorBuild)
  const result = normalizeSmokeResult(report.result, 'result')
  const validatedEntries = Array.isArray(report.authoringManifest?.validatedEntries)
    ? report.authoringManifest.validatedEntries
    : []
  const mapKindByUrl = new Map(
    validatedEntries
      .filter((entry) => typeof entry?.mapAssetPath === 'string' && typeof entry?.mapKind === 'string')
      .map((entry) => [entry.mapAssetPath, entry.mapKind]),
  )
  const smokeReports = Array.isArray(report.smokeReports) ? report.smokeReports : []

  const smokeMaps = smokeReports.map((smokeReport, index) => {
    const mapUrl = assertString(smokeReport.mapUrl, `smokeReports[${index}].mapUrl`)
    const mapKind = mapKindByUrl.get(mapUrl)
    const label =
      (mapKind && FAMILY_LABELS[mapKind]) ||
      buildFallbackLabel(mapUrl)

    return {
      map_url: mapUrl,
      label,
      result: normalizeSmokeResult(smokeReport.result, `smokeReports[${index}].result`),
    }
  })

  return {
    lane: 'Windows Unreal packaged validation',
    result,
    generated_at: generatedAtUtc,
    configuration,
    skip_build: skipBuild,
    pre_package_editor_build: prePackageEditorBuild,
    smoke_map_count: smokeMaps.length,
    smoke_maps: smokeMaps,
  }
}

async function main() {
  const checkOnly = process.argv.includes('--check')
  const sourceContent = await fs.readFile(sourcePath, 'utf8')
  const summary = buildSummary(parseJson(sourceContent, sourcePath))
  const serialized = `${JSON.stringify(summary, null, 2)}\n`

  if (checkOnly) {
    let existing = null
    try {
      existing = await fs.readFile(outputPath, 'utf8')
    } catch (error) {
      if (error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT') {
        console.error(`Generated summary missing: ${outputPath}`)
        process.exit(1)
      }
      throw error
    }

    if (existing !== serialized) {
      console.error('Generated web package-validation summary is stale.')
      console.error(`Refresh with: node ${path.relative(repoRoot, __filename)}`)
      process.exit(1)
    }

    console.log(`Validated packaged-validation summary freshness: ${path.relative(repoRoot, outputPath)}`)
    return
  }

  await fs.mkdir(path.dirname(outputPath), { recursive: true })
  await fs.writeFile(outputPath, serialized, 'utf8')
  console.log(`Wrote ${path.relative(repoRoot, outputPath)}`)
}

await main()
