const sha256 = (value) => typeof value === 'string' && /^[0-9a-f]{64}$/.test(value)
const canonical = (value) => Array.isArray(value)
  ? value.map(canonical)
  : value && typeof value === 'object'
    ? Object.fromEntries(Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => [key, canonical(entry)]))
    : value

export const productionDriftDecisions = [
  {
    taskId: 'TSN-PROD-DRIFT-000',
    operation: 'cut',
    classification: 'allowed_evolution',
    reasonCode: 'native-downstream-topology-stabilizes-after-edit-restore',
    rationale: 'FreeCAD deterministically evolves the downstream Fillet, Mirrored, and LinearPattern semantic topology after a Pocket Length edit/restore while restoring their geometry; the evolved topology and mapped names remain stable through save, reopen, and resave.',
  },
  {
    taskId: 'TSN-PROD-DRIFT-001',
    operation: 'rotate',
    classification: 'allowed_evolution',
    reasonCode: 'native-downstream-topology-stabilizes-after-edit-restore',
    rationale: 'FreeCAD deterministically evolves the downstream Mirrored and LinearPattern semantic topology after a Rotate Angle edit/restore while restoring their geometry; the evolved topology and mapped names remain stable through save, reopen, and resave.',
  },
]

export const same = (left, right) => JSON.stringify(canonical(left)) === JSON.stringify(canonical(right))

const stageFingerprint = (driftReplay, ordinal, phase) => {
  const mutation = driftReplay.mutation
  const persistence = driftReplay.persistence?.[phase]?.[ordinal]
  if (!persistence) throw new Error(`${driftReplay.operation}/${ordinal} lacks ${phase} persistence evidence.`)
  return {
    geometrySignature: persistence.geometrySignature,
    semanticTopologyDigest: persistence.semanticTopologyDigest,
    mappedNames: persistence.mappedNames,
    mappedNameDigest: persistence.mappedNameDigest,
  }
}

export const buildProductionDriftSnapshot = (report, operation) => {
  const driftReplay = report?.driftReplays?.find((entry) => entry.operation === operation)
  if (!driftReplay) throw new Error(`${operation} has no isolated production drift replay.`)
  const mutation = driftReplay.mutation
  const ordinals = mutation.restoreTopologyDriftOrdinals
  if (!Array.isArray(ordinals) || ordinals.length === 0) throw new Error(`${operation} has no recovered production topology drift.`)
  const stages = ordinals.map((ordinal) => ({
    ordinal,
    operation: driftReplay.persistence.initial[ordinal].operation,
    name: driftReplay.persistence.initial[ordinal].name,
    before: {
      geometrySignature: mutation.beforeGeometrySignatures[ordinal],
      semanticTopologyDigest: mutation.beforeTopologyDigests[ordinal],
    },
    edited: {
      geometrySignature: mutation.editedGeometrySignatures[ordinal],
      semanticTopologyDigest: mutation.editedTopologyDigests[ordinal],
    },
    restored: {
      geometrySignature: mutation.restoredGeometrySignatures[ordinal],
      semanticTopologyDigest: mutation.restoredTopologyDigests[ordinal],
    },
    persistence: Object.fromEntries(['initial', 'reopened', 'resaved'].map((phase) => [phase, stageFingerprint(driftReplay, ordinal, phase)])),
  }))
  return {
    operation,
    contract: {
      featureName: mutation.featureName,
      typeId: mutation.typeId,
      propertyPath: mutation.propertyPath,
    },
    values: {
      before: mutation.beforeParameter,
      edited: mutation.editedParameter,
      restored: mutation.restoredParameter,
    },
    driftOrdinals: ordinals,
    stages,
    checks: {
      parameterRestored: mutation.parameterChanged === true && same(mutation.beforeParameter, mutation.restoredParameter),
      geometryRestored: mutation.restoredGeometrically === true && mutation.restoredExactly === true && same(mutation.beforeGeometrySignatures, mutation.restoredGeometrySignatures),
      topologyEvolved: stages.every(({ before, restored }) => before.semanticTopologyDigest !== restored.semanticTopologyDigest),
      restoredMatchesInitial: driftReplay.checks?.restoredMatchesInitial === true && stages.every(({ restored, persistence }) => same(restored.geometrySignature, persistence.initial.geometrySignature) && restored.semanticTopologyDigest === persistence.initial.semanticTopologyDigest),
      persistenceStable: driftReplay.checks?.geometryStable === true && driftReplay.checks?.topologyStable === true && driftReplay.checks?.mappedNamesStable === true && stages.every(({ persistence }) => ['reopened', 'resaved'].every((phase) => same(persistence.initial, persistence[phase]))),
    },
  }
}

export const validateProductionDriftSnapshot = (snapshot) => {
  if (!snapshot || typeof snapshot.operation !== 'string' || !snapshot.operation) throw new Error('production drift snapshot has no operation identity.')
  if (!Array.isArray(snapshot.driftOrdinals) || snapshot.driftOrdinals.length === 0 || snapshot.stages?.length !== snapshot.driftOrdinals.length) throw new Error(`${snapshot.operation} has an invalid drift-stage set.`)
  if (!same(snapshot.stages.map(({ ordinal }) => ordinal), snapshot.driftOrdinals)) throw new Error(`${snapshot.operation} drift-stage identities are inconsistent.`)
  for (const stage of snapshot.stages) {
    if (!Number.isInteger(stage.ordinal) || !stage.operation || !stage.name) throw new Error(`${snapshot.operation} has an invalid stage identity.`)
    for (const phase of ['before', 'edited', 'restored']) {
      if (!Array.isArray(stage[phase]?.geometrySignature) || !sha256(stage[phase]?.semanticTopologyDigest)) throw new Error(`${snapshot.operation}/${stage.name}/${phase} has an invalid fingerprint.`)
    }
    for (const phase of ['initial', 'reopened', 'resaved']) {
      const value = stage.persistence?.[phase]
      if (!Array.isArray(value?.geometrySignature) || !value?.mappedNames || typeof value.mappedNames !== 'object' || !sha256(value?.semanticTopologyDigest) || !sha256(value?.mappedNameDigest)) throw new Error(`${snapshot.operation}/${stage.name}/${phase} has invalid persistence evidence.`)
    }
  }
  if (!Object.values(snapshot.checks ?? {}).every((value) => value === true)) throw new Error(`${snapshot.operation} does not satisfy the allowed-evolution evidence contract.`)
}
