import { createMockFacade } from './facade/mockFacade'
import { createAssembly } from './facade/assembly'
import { createBimModel } from './facade/bim'
import { createEngineeringProject } from './facade/engineeringProject'
import { createMeshDocument } from './facade/mesh'
import { createSurfaceDocument } from './facade/surface'

type EngineeringReport = { schemaVersion: 1; status: 'pass' | 'failed'; browserId: 'chrome'; crossOriginIsolated: boolean; integrity?: { complete: boolean; artifacts: number; kinds: number; missingKinds: number; missingRefs: number; projectVersion: number; artifactVersions: number[]; reopenedComplete: boolean }; workflow?: { assemblyComponents: number; bimElements: number; meshTriangles: number; surfacePatches: number; exports: { assemblyBytes: number; ifcBytes: number; meshObjBytes: number; surfaceObjBytes: number }; edited: { assemblyX: number; fireRating: string; meshMinX: number; surfaceOffset: number } }; scale?: { components: number; bomRows: number; durationMs: number; budgetMs: number }; persistence?: { mode: string; byteLength: number; hash: string; roundTrip: boolean; released: boolean }; opfs?: { markerSuite: string; artifacts: number; markerRemoved: boolean }; afterRelease?: { shapeCount: number; kernelReferenceCount: number }; error?: string }
const sha256 = async (bytes: Uint8Array) => [...new Uint8Array(await crypto.subtle.digest('SHA-256', Uint8Array.from(bytes).buffer))].map((value) => value.toString(16).padStart(2, '0')).join('')

const run = async (): Promise<EngineeringReport> => {
  const facade = createMockFacade()
  const report: EngineeringReport = { schemaVersion: 1, status: 'failed', browserId: 'chrome', crossOriginIsolated: globalThis.crossOriginIsolated === true }
  try {
    if (!report.crossOriginIsolated || !navigator.storage?.getDirectory) throw new Error('Chrome engineering closure evidence requires isolated OPFS.')
    await facade.project.list()
    const shape = await facade.geometry.createBox({ documentId: 'engineering', documentVersion: 1, width: 5, length: 2, height: 3 })
    const assembly = createAssembly('assembly', 'Assembly')
    assembly.addComponent({ id: 'base', sourceObjectId: shape.id, label: 'Base', grounded: true })
    assembly.addComponent({ id: 'part', sourceObjectId: shape.id, label: 'Part', grounded: false, placement: { x: 4 } })
    assembly.addConnector({ id: 'base-c', componentId: 'base', origin: { x: 0, y: 0, z: 0 }, axis: { x: 1, y: 0, z: 0 } })
    assembly.addConnector({ id: 'part-c', componentId: 'part', origin: { x: 0, y: 0, z: 0 }, axis: { x: 1, y: 0, z: 0 } })
    assembly.addJoint({ id: 'distance', kind: 'distance', first: 'base-c', second: 'part-c', value: 3 })
    const assemblySolved = assembly.solve()
    const bim = createBimModel('bim', 'BIM')
    bim.addSite({ id: 'site', label: 'Site' }); bim.addBuilding({ id: 'building', label: 'Building', siteId: 'site' }); bim.addLevel({ id: 'level', label: 'Level 1', elevation: 0, buildingId: 'building' }); bim.addSpace({ id: 'space', label: 'Space', levelId: 'level', area: 10 }); bim.addMaterial({ id: 'material', name: 'Concrete' }); bim.addElement({ id: 'wall', label: 'Wall', type: 'wall', shapeId: shape.id, levelId: 'level', spaceId: 'space', properties: {}, quantity: { area: 10 } }); bim.assignMaterial('wall', 'material')
    const mesh = createMeshDocument('mesh', 'Mesh', await facade.geometry.mesh(shape, 0.05)); mesh.weldVertices(); mesh.removeDegenerate()
    const surface = createSurfaceDocument('surface', 'Surface'); surface.addBezier('panel', [[[0, 0, 0], [0, 1, 0]], [[1, 0, 0], [1, 1, 0]]]); surface.fill('cap', [[0, 0, 0], [0, 1, 0], [1, 1, 0], [1, 0, 0]]); surface.offset('cap', 'cap-offset', 0.25); surface.loft('loft', [[[0, 0, 0], [1, 0, 0]], [[0, 0, 1], [1, 0, 1]]])
    const project = createEngineeringProject('engineering', 'Mixed engineering project')
    project.add({ id: 'assembly', kind: 'Assembly', sourceRefs: [], payload: { snapshot: assemblySolved } })
    project.add({ id: 'bim', kind: 'BIM', sourceRefs: ['assembly'], payload: { snapshot: bim.snapshot() } })
    project.add({ id: 'mesh', kind: 'Mesh', sourceRefs: ['bim'], payload: { snapshot: mesh.snapshot() } })
    project.add({ id: 'surface', kind: 'Surface', sourceRefs: ['mesh'], payload: { snapshot: surface.snapshot() } })
    assembly.setPlacement('part', { x: 6 })
    const editedAssembly = assembly.snapshot()
    bim.setElementProperty('wall', 'FireRating', 'A1')
    mesh.transform({ translation: [1, 0, 0], scale: 1.5 })
    const editedSurface = surface.offset('panel', 'panel-offset', 0.5)
    const assemblyExport = new TextEncoder().encode(JSON.stringify(editedAssembly))
    const ifcExport = new TextEncoder().encode(bim.exportIfc('IFC4'))
    const meshExport = new TextEncoder().encode(mesh.exportObj())
    const surfaceExport = new TextEncoder().encode(surface.exportObj())
    project.update('assembly', { payload: { snapshot: editedAssembly, exportBytes: assemblyExport.byteLength } })
    project.update('bim', { payload: { snapshot: bim.snapshot(), exportBytes: ifcExport.byteLength } })
    project.update('mesh', { payload: { snapshot: mesh.snapshot(), exportBytes: meshExport.byteLength } })
    project.update('surface', { payload: { snapshot: surface.snapshot(), exportBytes: surfaceExport.byteLength } })
    const scaleStarted = performance.now()
    const large = createAssembly('large', 'Large mixed assembly')
    for (let index = 0; index < 1000; index += 1) large.addComponent({ id: `part-${index}`, sourceObjectId: `shape-${index % 20}`, label: `Part ${index % 20}`, grounded: index === 0, placement: { x: index } })
    const largeBom = large.bom()
    const scaleDurationMs = performance.now() - scaleStarted
    const integrity = project.integrity()
    const serialized = project.save()
    const reopened = createEngineeringProject('reopened', 'Reopened')
    const reopenedSnapshot = reopened.load(serialized)
    const reopenedIntegrity = reopened.integrity()
    const payload = new TextEncoder().encode(serialized)
    const stored = await facade.project.resource.put(payload, 'application/vnd.bitbybit.engineering+json')
    const loaded = await facade.project.resource.get(stored.hash)
    const roundTrip = loaded !== null && await sha256(loaded) === await sha256(payload)
    await facade.project.resource.release(stored.hash)
    const released = await facade.project.resource.get(stored.hash) === null
    const directory = await navigator.storage.getDirectory(); const markerName = 'engineering-chrome-marker.json'; const marker = await directory.getFileHandle(markerName, { create: true }); const writable = await marker.createWritable(); await writable.write(JSON.stringify({ suite: 'ENG-CLOSURE', artifacts: integrity.artifacts })); await writable.close(); const markerPayload = JSON.parse(await (await marker.getFile()).text()) as { suite: string; artifacts: number }; await directory.removeEntry(markerName); let markerRemoved = false; try { await directory.getFileHandle(markerName) } catch (error) { markerRemoved = error instanceof DOMException && error.name === 'NotFoundError' }
    report.integrity = { complete: integrity.complete, artifacts: integrity.artifacts, kinds: integrity.kinds.length, missingKinds: integrity.missingKinds.length, missingRefs: integrity.missingRefs.length, projectVersion: project.snapshot().version, artifactVersions: project.snapshot().artifacts.map((artifact) => artifact.version).sort(), reopenedComplete: reopenedIntegrity.complete && reopenedSnapshot.artifacts.length === 4 }
    report.workflow = { assemblyComponents: editedAssembly.components.length, bimElements: bim.snapshot().elements.length, meshTriangles: mesh.snapshot().triangles.length, surfacePatches: surface.snapshot().patches.length, exports: { assemblyBytes: assemblyExport.byteLength, ifcBytes: ifcExport.byteLength, meshObjBytes: meshExport.byteLength, surfaceObjBytes: surfaceExport.byteLength }, edited: { assemblyX: editedAssembly.components.find((component) => component.id === 'part')?.placement.x ?? Number.NaN, fireRating: String(bim.snapshot().elements.find((element) => element.id === 'wall')?.properties.FireRating ?? ''), meshMinX: mesh.analyze().bounds.min[0], surfaceOffset: editedSurface.poles[0][0][2] - surface.snapshot().patches.find((patch) => patch.id === 'panel')!.poles[0][0][2] } }
    report.scale = { components: large.snapshot().components.length, bomRows: largeBom.length, durationMs: scaleDurationMs, budgetMs: 1000 }
    report.persistence = { mode: facade.project.capabilities().mode, byteLength: stored.byteLength, hash: stored.hash, roundTrip, released }
    report.opfs = { markerSuite: markerPayload.suite, artifacts: markerPayload.artifacts, markerRemoved }
    report.status = report.integrity.complete && report.integrity.artifacts === 4 && report.integrity.kinds === 4 && report.integrity.missingKinds === 0 && report.integrity.missingRefs === 0 && report.integrity.projectVersion === 8 && JSON.stringify(report.integrity.artifactVersions) === JSON.stringify([2, 2, 2, 2]) && report.integrity.reopenedComplete && report.workflow.assemblyComponents === 2 && report.workflow.bimElements === 1 && report.workflow.meshTriangles > 0 && report.workflow.surfacePatches === 5 && report.workflow.edited.assemblyX === 6 && report.workflow.edited.fireRating === 'A1' && report.workflow.edited.meshMinX === -2.75 && report.workflow.edited.surfaceOffset === 0.5 && Object.values(report.workflow.exports).every((value) => value > 0) && report.scale.components === 1000 && report.scale.bomRows === 20 && report.scale.durationMs <= report.scale.budgetMs && report.persistence.mode === 'sqlite-opfs' && report.persistence.roundTrip && report.persistence.released && report.opfs.markerSuite === 'ENG-CLOSURE' && report.opfs.artifacts === 4 && report.opfs.markerRemoved ? 'pass' : 'failed'
  } catch (error) { report.error = error instanceof Error ? error.stack || error.message : String(error) }
  finally { facade.geometry.dispose(); await new Promise((resolve) => setTimeout(resolve, 0)); const capabilities = facade.geometry.capabilities(); report.afterRelease = { shapeCount: capabilities.shapeCount, kernelReferenceCount: capabilities.kernelReferenceCount }; if (report.afterRelease.shapeCount !== 0 || report.afterRelease.kernelReferenceCount !== 0) { report.status = 'failed'; report.error = `${report.error ? `${report.error} ` : ''}Shape ownership gate failed.` } }
  return report
}
run().then((report) => { ;(window as Window & { __bitbybitEngineeringReport?: EngineeringReport }).__bitbybitEngineeringReport = report; document.documentElement.dataset.status = report.status; document.querySelector('#result')!.textContent = JSON.stringify(report, null, 2) }).catch((error) => { document.documentElement.dataset.status = 'failed'; document.querySelector('#result')!.textContent = error instanceof Error ? error.stack || error.message : String(error) })
export {}
