import { createMockFacade } from './facade/mockFacade'
import { createSurfaceDocument } from './facade/surface'

type SurfaceReport = { schemaVersion: 1; status: 'pass' | 'failed'; browserId: 'chrome'; crossOriginIsolated: boolean; model?: { patches: number; poles: number; trimmed: number; sewn: number; continuity: string; fillKind: string; offsetDistance: number; topoRefs: number; objBytes: number }; persistence?: { mode: string; byteLength: number; roundTrip: boolean; released: boolean }; opfs?: { markerSuite: string; patches: 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<SurfaceReport> => {
  const facade = createMockFacade()
  const report: SurfaceReport = { schemaVersion: 1, status: 'failed', browserId: 'chrome', crossOriginIsolated: globalThis.crossOriginIsolated === true }
  try {
    if (!report.crossOriginIsolated || !navigator.storage?.getDirectory) throw new Error('Chrome surface evidence requires isolated OPFS.')
    await facade.project.list()
    const shape = await facade.geometry.createBox({ documentId: 'surface', documentVersion: 1, width: 2, length: 2, height: 1 })
    const surface = createSurfaceDocument('surfaces', 'Surface model')
    surface.addBezier('A', [[[0, 0, 0], [0, 1, 0]], [[1, 0, 0], [1, 1, 0]]])
    surface.addBspline('B', [[[1, 0, 0], [1, 1, 0]], [[2, 0, 0], [2, 1, 0]]], { degreeU: 1, degreeV: 1 })
    surface.trim('B', [0, 0.8], [0, 1])
    surface.sew(['A', 'B'])
    surface.loft('L', [[[0, 0, 0], [1, 0, 0]], [[0, 0, 1], [1, 0, 1]]], { ruled: true })
    const fill = surface.fill('F', [[0, 0, 0], [0, 1, 0], [1, 1, 0], [1, 0, 0]])
    const offset = surface.offset('F', 'O', 1.5)
    const quality = surface.analyze()
    const topoRefs = surface.topologyRefs('F')
    const obj = new TextEncoder().encode(surface.exportObj())
    const payload = new TextEncoder().encode(JSON.stringify(surface.snapshot()))
    const stored = await facade.project.resource.put(payload, 'application/vnd.bitbybit.surface+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 = 'surface-chrome-marker.json'
    const marker = await directory.getFileHandle(markerName, { create: true })
    const writable = await marker.createWritable(); await writable.write(JSON.stringify({ suite: 'SURF-CORE', patches: quality.patches })); await writable.close()
    const markerPayload = JSON.parse(await (await marker.getFile()).text()) as { suite: string; patches: number }
    await directory.removeEntry(markerName)
    let markerRemoved = false
    try { await directory.getFileHandle(markerName) } catch (error) { markerRemoved = error instanceof DOMException && error.name === 'NotFoundError' }
    const continuity = surface.continuity('A', 'B')
    report.model = { patches: quality.patches, poles: quality.poles, trimmed: quality.trimmed, sewn: surface.snapshot().sewn.length, continuity: continuity.relation, fillKind: fill.kind, offsetDistance: offset.poles[0][0][2] - fill.poles[0][0][2], topoRefs: topoRefs.filter((ref) => ref.status === 'stable' && ref.persistentId.startsWith('F:')).length, objBytes: obj.byteLength }
    report.persistence = { mode: facade.project.capabilities().mode, byteLength: stored.byteLength, roundTrip, released }
    report.opfs = { markerSuite: markerPayload.suite, patches: markerPayload.patches, markerRemoved }
    report.status = shape.id.length > 0 && report.model.patches === 5 && report.model.poles === 20 && report.model.trimmed === 1 && report.model.sewn === 1 && report.model.continuity === 'C0' && report.model.fillKind === 'bezier' && report.model.offsetDistance === 1.5 && report.model.topoRefs === 4 && report.model.objBytes > 0 && report.persistence.mode === 'sqlite-opfs' && report.persistence.roundTrip && report.persistence.released && report.opfs.markerSuite === 'SURF-CORE' && report.opfs.patches === 5 && 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 & { __bitbybitSurfaceReport?: SurfaceReport }).__bitbybitSurfaceReport = 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 {}
