import createProbe from './dist/freecad-private-naming-source-probe.js'
import { parseElementMap2 } from '../../src/facade/elementMap2'
import {
  captureFreeCadPrivateNamingEvidence,
  createFreeCadPrivateNamingAbiRequest,
  probeFreeCadPrivateNamingAbi,
  type NativeFreeCadNamingAbiModule,
} from '../../src/facade/nativeNamingAbi'

type CandidateProbe = {
  freecadNamingCandidateAbiVersion(): number
  freecadNamingCandidateCapabilitiesJson(): string
  freecadNamingCandidateEvidenceJson(requestJson: string): string
}

const native = await createProbe() as CandidateProbe
const candidate: NativeFreeCadNamingAbiModule = {
  freecadNamingAbiVersion: () => native.freecadNamingCandidateAbiVersion(),
  freecadNamingCapabilitiesJson: () => native.freecadNamingCandidateCapabilitiesJson(),
  freecadNamingEvidenceJson: (requestJson) => {
    const response = JSON.parse(native.freecadNamingCandidateEvidenceJson(requestJson)) as Record<string, unknown>
    const elementMap2Text = response.elementMap2Text
    if (typeof elementMap2Text !== 'string') throw new TypeError('Candidate response omitted native ElementMap2 text.')
    delete response.elementMap2Text
    response.elementMap2 = parseElementMap2(elementMap2Text)
    return JSON.stringify(response)
  },
}

const abiProbe = probeFreeCadPrivateNamingAbi(candidate)
if (abiProbe.availability !== 'available') throw new Error(`Candidate ABI probe failed: ${abiProbe.reason}`)
const request = createFreeCadPrivateNamingAbiRequest({
  requestId: 'source-candidate-request',
  documentId: 'source-candidate-document',
  documentVersion: 1,
  operationId: 'source-candidate-cut',
  operation: 'cut',
  stageId: 'source-candidate:stage:0',
  resultObjectId: 'source-candidate:result',
  resultObjectTag: 99,
  inputs: [
    { inputId: 'object', objectId: 'source-candidate:object', role: 'object', step: 'ISO-10303-21; probe object', objectTag: 42 },
    { inputId: 'tool', objectId: 'source-candidate:tool', role: 'tool', step: 'ISO-10303-21; probe tool', objectTag: 43 },
  ],
  stages: [{ stageId: 'source-candidate:stage:0', operation: 'cut', inputIds: ['object', 'tool'], ordinal: 0 }],
  resultStep: 'ISO-10303-21; probe result',
  history: {
    provider: 'occt-native',
    occtVersion: '8.0.0',
    hasModified: true,
    hasGenerated: false,
    hasDeleted: false,
    resultStep: 'ISO-10303-21; probe result',
    records: [{ relation: 'modified', source: 'object', kind: 'face', sourceIndex: 0, resultIndex: 2 }],
  },
})
const evidence = captureFreeCadPrivateNamingEvidence(candidate, request, abiProbe)
if (!evidence || evidence.status !== 'native-evidence') throw new Error('Candidate ABI returned no native evidence.')
if (evidence.mappedNames?.[0]?.reference.name !== '#1' || evidence.mappedNames[0].reference.postfix !== ';:H2a,F') throw new Error('Candidate ABI mapped-name reference is unexpected.')
if (evidence.stringHasher?.entries.length !== 1 || evidence.elementMap2?.maps.length !== 1) throw new Error('Candidate ABI native resource evidence is incomplete.')

console.log(JSON.stringify({
  status: 'freecad-private-naming-abi-candidate-pass',
  descriptor: abiProbe.descriptor,
  evidence: {
    stageId: evidence.stageId,
    resultObjectId: evidence.resultObjectId,
    mappedNames: evidence.mappedNames.length,
    stringHasherEntries: evidence.stringHasher.entries.length,
    elementMaps: evidence.elementMap2.maps.length,
  },
  productionCallbacksExported: false,
  productionWorkerLinked: false,
}, null, 2))
