import { createHash } from 'node:crypto'
import { readFile, writeFile } from 'node:fs/promises'
import { resolve } from 'node:path'

const root = resolve(new URL('..', import.meta.url).pathname)
const runtimePath = resolve(root, '.cache/freecad/reference-desktop.json')
const sourcePaths = [
  '.cache/freecad/FreeCAD/src/App/Property.h',
  '.cache/freecad/FreeCAD/src/App/Property.cpp',
  '.cache/freecad/FreeCAD/src/App/PropertyStandard.h',
  '.cache/freecad/FreeCAD/src/App/PropertyStandard.cpp',
  '.cache/freecad/FreeCAD/src/Base/Color.h',
  '.cache/freecad/FreeCAD/src/Base/Stream.h',
  '.cache/freecad/FreeCAD/src/Base/Stream.cpp',
]
const outputPath = resolve(root, 'config/freecad-property-colorlist-inventory.json')
const runtimeContent = await readFile(runtimePath)
const runtime = JSON.parse(runtimeContent)
const sourceContents = await Promise.all(sourcePaths.map((path) => readFile(resolve(root, path))))
const fail = (message) => { throw new Error(`FreeCAD PropertyColorList inventory generation failed: ${message}`) }

if (runtime.schemaVersion !== 1 || runtime.freecadVersion !== '1.1.1' || runtime.gitCommit !== '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d') fail('desktop oracle is not the locked FreeCAD baseline')
const records = []
for (const objectType of runtime.runtimeObjects?.types ?? []) {
  for (const property of objectType.properties ?? []) {
    if (property.typeId !== 'App::PropertyColorList') continue
    records.push({
      objectTypeId: objectType.typeId,
      objectAvailable: objectType.available === true,
      probeStatus: objectType.probeStatus,
      propertyName: property.name,
      group: property.group,
      status: property.status,
      defaultValue: property.default,
      valueModel: {
        kind: 'ordered-rgba-color-list',
        elementRepresentation: 'four-channel-float-tuple',
        packedElementRepresentation: '0xRRGGBBAA',
        alphaSemantics: '1-opaque-0-transparent',
        writable: property.status.length === 0,
      },
      inputs: {
        collection: ['sequence', 'iterable', 'single-tuple-color-value', 'single-non-sequence-color-value', 'integer-index-dictionary'],
        dictionaryAppendIndexes: [-1, 'current-size'],
        elementSetters: ['float-tuple-3-or-4', 'integer-tuple-3-or-4', 'packed-integer-0xRRGGBBAA'],
      },
      dependencies: [],
      applicability: {
        requiredObjectTypeId: objectType.typeId,
        source: 'Document.supportedTypes runtime inventory',
        shapeRequired: false,
      },
    })
  }
}
records.sort((left, right) => `${left.objectTypeId}.${left.propertyName}`.localeCompare(`${right.objectTypeId}.${right.propertyName}`))
if (records.length !== 2) fail(`expected two native App::PropertyColorList records, found ${records.length}`)
const report = {
  schemaVersion: 1,
  status: 'pass',
  baseline: { freecadVersion: runtime.freecadVersion, commit: runtime.gitCommit },
  propertyType: 'App::PropertyColorList',
  recordCount: records.length,
  records,
  storage: {
    xmlElement: 'ColorList',
    fileAttribute: 'file',
    nonEmptyExternalResourceName: 'property-name',
    emptyResourceName: '',
    externalBinary: { byteOrder: 'little-endian', count: 'uint32', element: 'uint32-packed-0xRRGGBBAA' },
    legacyBeforeVersion: '1.1',
    legacyConversion: 'invert-alpha-channel',
  },
  provenance: {
    runtime: { path: '.cache/freecad/reference-desktop.json', bytes: runtimeContent.length, sha256: createHash('sha256').update(runtimeContent).digest('hex') },
    sources: sourcePaths.map((path, index) => ({ path, bytes: sourceContents[index].length, sha256: createHash('sha256').update(sourceContents[index]).digest('hex') })),
  },
  classification: 'opaque-fcstd-proxy',
  nextPhases: ['B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'],
}
await writeFile(outputPath, `${JSON.stringify(report, null, 2)}\n`)
console.log(JSON.stringify({ status: 'freecad-property-colorlist-inventory-generated', output: 'config/freecad-property-colorlist-inventory.json', propertyType: report.propertyType, recordCount: report.recordCount }, null, 2))
