import { isDeepStrictEqual } from 'node:util'
import { readFile } from 'node:fs/promises'
import { resolve } from 'node:path'

const root = resolve(new URL('..', import.meta.url).pathname)
const report = JSON.parse(await readFile(resolve(root, 'config/freecad-property-color-mutation.json'), 'utf8'))
const fail = (message) => { throw new Error(`FreeCAD PropertyColor mutation check failed: ${message}`) }
if (report.schemaVersion !== 1 || report.status !== 'pass' || report.baselineId !== 'freecad-1.1.1-property-color-mutation' || report.freecadVersion !== '1.1.1' || report.gitCommit !== '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d' || report.propertyType !== 'App::PropertyColor') fail('baseline is invalid')
if (report.caseCount !== 8 || !Array.isArray(report.cases) || report.cases.length !== 8 || new Set(report.cases.map(({ objectTypeId }) => objectTypeId)).size !== 8) fail('mutation case inventory is incomplete')
const target = [0.125, 0.375, 0.625, 0.875]
const expectedHosts = [
  ['App::FeatureTest', 'Colour', [0, 0, 0, 1], 1],
  ['App::FeatureTestException', 'Colour', [0, 0, 0, 1], 1],
  ['App::Part', 'Color', [1, 1, 1, 0], 9],
  ['Assembly::AssemblyLink', 'Color', [1, 1, 1, 0], 9],
  ['Assembly::AssemblyObject', 'Color', [1, 1, 1, 0], 9],
  ['TechDraw::DrawViewAnnotation', 'TextColor', [0, 0, 0, 1], 1],
  ['TechDraw::DrawViewDraft', 'Color', [0, 0, 0, 1], 1],
  ['TechDraw::DrawViewSpreadsheet', 'TextColor', [0, 0, 0, 1], 2],
]
const byType = new Map(report.cases.map((entry) => [entry.objectTypeId, entry]))
for (const [typeId, propertyName, original, objectCount] of expectedHosts) {
  const entry = byType.get(typeId)
  if (entry?.propertyName !== propertyName || !isDeepStrictEqual(entry.target, target) || entry.editRecomputeResult !== true || entry.restoreRecomputeResult !== true || entry.mutationDetected !== true || entry.restoredExactly !== true) fail(`${typeId} mutation boundary changed`)
  if (typeId === 'TechDraw::DrawViewSpreadsheet') {
    if (entry.setup?.kind !== 'spreadsheet-source' || entry.setup.objectTypeId !== 'Spreadsheet::Sheet' || entry.setup.objectName !== 'MutationSource') fail('Spreadsheet mutation setup changed')
  } else if (entry.setup?.kind !== 'none') fail(`${typeId} has unexpected mutation setup`)
  if (!isDeepStrictEqual(entry.before?.value, original) || !isDeepStrictEqual(entry.touchedAfterEdit?.value, target) || !isDeepStrictEqual(entry.edited?.value, target) || !isDeepStrictEqual(entry.touchedAfterRestore?.value, original) || !isDeepStrictEqual(entry.restored?.value, original)) fail(`${typeId} mutation values changed`)
  const objectSet = entry.before.objectSet
  if (objectSet?.length !== objectCount || !objectSet.some(({ typeId: candidateType }) => candidateType === typeId)) fail(`${typeId} mutation object set changed`)
  for (const phase of ['before', 'touchedAfterEdit', 'edited', 'touchedAfterRestore', 'restored']) {
    const snapshot = entry[phase]
    if (snapshot.propertyTypeId !== 'App::PropertyColor' || !isDeepStrictEqual(snapshot.propertyStatus, []) || !isDeepStrictEqual(snapshot.editorMode, []) || snapshot.shape?.applicable !== false || !isDeepStrictEqual(snapshot.objectSet, objectSet)) fail(`${typeId} ${phase} native metadata changed`)
  }
  if (typeId === 'App::FeatureTestException') {
    if (entry.hostExecution !== 'intrinsic-test-exception' || !isDeepStrictEqual(entry.before.objectState, ['Up-to-date']) || entry.before.statusString !== 'Valid' || !isDeepStrictEqual(entry.touchedAfterEdit.objectState, ['Touched']) || entry.touchedAfterEdit.statusString !== 'Touched') fail('FeatureTestException initial mutation sequence changed')
    for (const phase of ['edited', 'touchedAfterRestore', 'restored']) if (!isDeepStrictEqual(entry[phase].objectState, ['Touched', 'Invalid']) || entry[phase].statusString !== 'FeatureTestException::execute(): Testexception  ;-)') fail(`FeatureTestException ${phase} intrinsic diagnostic changed`)
  } else {
    if (entry.hostExecution !== 'normal' || !isDeepStrictEqual(entry.before.objectState, ['Up-to-date']) || entry.before.statusString !== 'Valid' || !isDeepStrictEqual(entry.touchedAfterEdit.objectState, ['Touched']) || entry.touchedAfterEdit.statusString !== 'Touched' || !isDeepStrictEqual(entry.edited.objectState, ['Up-to-date']) || entry.edited.statusString !== 'Valid' || !isDeepStrictEqual(entry.touchedAfterRestore.objectState, ['Touched']) || entry.touchedAfterRestore.statusString !== 'Touched' || !isDeepStrictEqual(entry.restored.objectState, ['Up-to-date']) || entry.restored.statusString !== 'Valid') fail(`${typeId} mutation state sequence changed`)
  }
}
console.log(JSON.stringify({ status: 'freecad-property-color-mutation-pass', cases: report.caseCount, target, mutated: report.cases.filter(({ mutationDetected }) => mutationDetected).length, restoredExactly: report.cases.filter(({ restoredExactly }) => restoredExactly).length, normalStateSequence: ['Valid', 'Touched', 'Valid', 'Touched', 'Valid'], intrinsicHostDiagnostic: 'App::FeatureTestException' }, null, 2))
