import { cloneSketch, type SketchConstraint, type SketchSnapshot, type SketchSolveResult } from './sketcher'
import type { SketchSolverCapabilities } from './sketchSolverProtocol'

export type PlanegcsDoubleVector = {
  size(): number
  get(index: number): number
  delete(): void
}

export type PlanegcsWasmModule = {
  solveHorizontalDistance(startX: number, startY: number, endX: number, endY: number, targetLength: number): PlanegcsDoubleVector
  solveVerticalDistance(startX: number, startY: number, endX: number, endY: number, targetLength: number): PlanegcsDoubleVector
  solveDistanceX(startX: number, startY: number, endX: number, endY: number, targetDistance: number): PlanegcsDoubleVector
  solveDistanceY(startX: number, startY: number, endX: number, endY: number, targetDistance: number): PlanegcsDoubleVector
  solveAngle(startX: number, startY: number, endX: number, endY: number, targetLength: number, targetAngle: number): PlanegcsDoubleVector
  solveCircleRadius(centerX: number, centerY: number, radius: number, targetRadius: number): PlanegcsDoubleVector
  solveCircleDiameter(centerX: number, centerY: number, radius: number, targetDiameter: number): PlanegcsDoubleVector
  solveEqualLines(firstStartX: number, firstStartY: number, firstEndX: number, firstEndY: number, secondStartX: number, secondStartY: number, secondEndX: number, secondEndY: number): PlanegcsDoubleVector
  solveEqualCircles(firstCenterX: number, firstCenterY: number, firstRadius: number, secondCenterX: number, secondCenterY: number, secondRadius: number): PlanegcsDoubleVector
  solveTangentCircles(firstCenterX: number, firstCenterY: number, firstRadius: number, secondCenterX: number, secondCenterY: number, secondRadius: number): PlanegcsDoubleVector
  solvePointSymmetry?: (firstX: number, firstY: number, secondX: number, secondY: number, centerX: number, centerY: number) => PlanegcsDoubleVector
  solvePointOnLine?: (pointX: number, pointY: number, startX: number, startY: number, endX: number, endY: number, vertical: boolean) => PlanegcsDoubleVector
  solvePointOnCircle?: (pointX: number, pointY: number, centerX: number, centerY: number, radius: number) => PlanegcsDoubleVector
  solvePointOnArc?: (pointX: number, pointY: number, centerX: number, centerY: number, radius: number, startAngle: number, endAngle: number) => PlanegcsDoubleVector
  solvePointOnEllipse?: (pointX: number, pointY: number, centerX: number, centerY: number, focusX: number, focusY: number, minorRadius: number) => PlanegcsDoubleVector
  solvePointOnCubicBspline?: (pointX: number, pointY: number, pole0X: number, pole0Y: number, pole1X: number, pole1Y: number, pole2X: number, pole2Y: number, pole3X: number, pole3Y: number, pointParameter: number) => PlanegcsDoubleVector
  solveParallelLines(firstStartX: number, firstStartY: number, firstEndX: number, firstEndY: number, secondStartX: number, secondStartY: number, secondEndX: number, secondEndY: number, secondLength: number): PlanegcsDoubleVector
  solvePerpendicularLines(firstStartX: number, firstStartY: number, firstEndX: number, firstEndY: number, secondStartX: number, secondStartY: number, secondEndX: number, secondEndY: number, secondLength: number): PlanegcsDoubleVector
  solveCoincidentLines(firstStartX: number, firstStartY: number, firstEndX: number, firstEndY: number, secondStartX: number, secondStartY: number, secondEndX: number, secondEndY: number, secondLength: number): PlanegcsDoubleVector
  solveCoincidentLinePoints?: (firstStartX: number, firstStartY: number, firstEndX: number, firstEndY: number, secondStartX: number, secondStartY: number, secondEndX: number, secondEndY: number, secondLength: number, firstEnd: boolean, secondEnd: boolean) => PlanegcsDoubleVector
  solveSnellsLawLines?: (firstStartX: number, firstStartY: number, firstEndX: number, firstEndY: number, secondStartX: number, secondStartY: number, secondEndX: number, secondEndY: number, boundaryStartX: number, boundaryStartY: number, boundaryEndX: number, boundaryEndY: number, refractiveRatio: number, firstEnd: boolean, secondEnd: boolean) => PlanegcsDoubleVector
  solveEllipseInternalAlignment?: (centerX: number, centerY: number, majorRadius: number, minorRadius: number, rotation: number, alignmentType: number) => PlanegcsDoubleVector
  solveEllipseInternalAlignmentSet?: (centerX: number, centerY: number, majorRadius: number, minorRadius: number, rotation: number) => PlanegcsDoubleVector
  solveCubicBsplineWeight?: (pole0X: number, pole0Y: number, pole1X: number, pole1Y: number, pole2X: number, pole2Y: number, pole3X: number, pole3Y: number, weight0: number, weight1: number, weight2: number, weight3: number, controlPointIndex: number, targetWeight: number) => PlanegcsDoubleVector
}

export const PLANEGCS_WASM_CAPABILITIES: SketchSolverCapabilities = {
  providerId: 'freecad.planegcs-wasm',
  providerVersion: '1.1.1-embind-subset.23',
  engine: 'planegcs-wasm',
  availability: 'available',
  compatibility: 'experimental',
  supportedGeometry: ['point', 'line', 'circle', 'arc', 'ellipse', 'bspline'],
  supportedConstraints: ['horizontal', 'vertical', 'parallel', 'perpendicular', 'distance', 'distanceX', 'distanceY', 'angle', 'radius', 'diameter', 'equal', 'tangent', 'coincident', 'symmetric', 'pointOnObject', 'snellsLaw', 'internalAlignment', 'weight', 'block'],
  reason: 'Native adapter supports FreeCAD-style pre-solve Block, three-point Symmetric, horizontal/vertical Line and fixed Circle/Arc/Ellipse or monotonic clamped cubic B-spline PointOnObject, a three-Line Coincident/PointOnObject/SnellsLaw compound graph, Ellipse major/minor/focus InternalAlignment helpers, one clamped cubic B-spline Weight helper graph, one-line orientation/distance/distanceX/distanceY/angle, one-circle radius/diameter, two-line EqualLength and two-circle EqualRadius/Tangent subsets, plus two-line Parallel/Perpendicular and all four line-endpoint Coincident subsets.',
}

export class PlanegcsSubsetError extends Error {
  readonly code = 'PLANEGCS_SUBSET_UNSUPPORTED'

  constructor(message: string) {
    super(message)
    this.name = 'PlanegcsSubsetError'
  }
}

const isLineEndpointDistance = (constraint: SketchConstraint, geometryId: string) => {
  if (constraint.type !== 'distance' && constraint.type !== 'distanceX' && constraint.type !== 'distanceY') return false
  if (constraint.first.geometryId !== geometryId || constraint.second.geometryId !== geometryId) return false
  return (constraint.first.point === 'start' && constraint.second.point === 'end') || (constraint.first.point === 'end' && constraint.second.point === 'start')
}

const samePointRef = (first: { geometryId: string; point: string }, second: { geometryId: string; point: string }) => first.geometryId === second.geometryId && first.point === second.point

export const solvePlanegcsSubset = (module: PlanegcsWasmModule, input: SketchSnapshot): SketchSolveResult => {
  const snapshot = cloneSketch(input)
  if (snapshot.externalGeometry.length !== 0) throw new PlanegcsSubsetError('Native planegcs subset does not yet support external geometry.')
  const driving = snapshot.constraints.filter((constraint) => constraint.driving !== false)
  const blocks = driving.filter((constraint): constraint is Extract<SketchConstraint, { type: 'block' }> => constraint.type === 'block')
  if (snapshot.geometry.length === 1 && driving.length === 1 && blocks.length === 1) {
    if (blocks[0].geometryId !== snapshot.geometry[0].id) throw new PlanegcsSubsetError('Native planegcs Block subset must reference its single geometry.')
    return resultFor(snapshot, 0, 0, 0)
  }
  const symmetric = driving.filter((constraint): constraint is Extract<SketchConstraint, { type: 'symmetric' }> => constraint.type === 'symmetric')
  if (snapshot.geometry.length === 3 && snapshot.geometry.every((geometry) => geometry.type === 'point') && driving.length === 1 && symmetric.length === 1) {
    const constraint = symmetric[0]
    const refs = [constraint.first, constraint.second, constraint.center]
    if (refs.some((ref) => ref.point !== 'position') || new Set(refs.map((ref) => ref.geometryId)).size !== 3) throw new PlanegcsSubsetError('Native planegcs Symmetric subset requires three distinct Point geometries referenced by position.')
    const points = refs.map((ref) => snapshot.geometry.find((geometry) => geometry.id === ref.geometryId))
    if (points.some((geometry) => !geometry || geometry.type !== 'point')) throw new PlanegcsSubsetError('Native planegcs Symmetric subset requires three distinct Point geometries.')
    const [first, second, center] = points as Array<Extract<SketchSnapshot['geometry'][number], { type: 'point' }>>
    if (!module.solvePointSymmetry) throw new PlanegcsSubsetError('Native planegcs Symmetric subset is unavailable in this module build.')
    const vector = module.solvePointSymmetry(first.position.x, first.position.y, second.position.x, second.position.y, center.position.x, center.position.y)
    const values = readVector(vector, 8)
    const [solveStatus, firstX, firstY, secondX, secondY, centerX, centerY, residual] = values
    first.position = { x: firstX, y: firstY }
    second.position = { x: secondX, y: secondY }
    center.position = { x: centerX, y: centerY }
    return resultFor(snapshot, solveStatus, Math.abs(residual), 0)
  }
  const snellsLaw = driving.filter((constraint): constraint is Extract<SketchConstraint, { type: 'snellsLaw' }> & { boundaryGeometryId: string } => constraint.type === 'snellsLaw' && 'boundaryGeometryId' in constraint)
  if (snapshot.geometry.length === 3 && driving.length === 3 && snellsLaw.length === 1) {
    const constraint = snellsLaw[0]
    const coincident = driving.filter((entry): entry is Extract<SketchConstraint, { type: 'coincident' }> => entry.type === 'coincident')
    const pointOnBoundary = driving.filter((entry): entry is Extract<SketchConstraint, { type: 'pointOnObject' }> => entry.type === 'pointOnObject')
    if (coincident.length !== 1 || pointOnBoundary.length !== 1) throw new PlanegcsSubsetError('Native planegcs SnellsLaw subset requires one Coincident and one PointOnObject prerequisite constraint.')
    if (!('first' in constraint) || !('second' in constraint)) throw new PlanegcsSubsetError('Native planegcs SnellsLaw subset requires endpoint references on both rays.')
    if ((constraint.first.point !== 'start' && constraint.first.point !== 'end') || (constraint.second.point !== 'start' && constraint.second.point !== 'end')) throw new PlanegcsSubsetError('Native planegcs SnellsLaw subset requires start or end references on both rays.')
    if (!Number.isFinite(constraint.value) || !(constraint.value > 0)) throw new PlanegcsSubsetError('Native planegcs SnellsLaw refractive ratio must be positive and finite.')
    const first = snapshot.geometry.find((geometry) => geometry.id === constraint.first.geometryId)
    const second = snapshot.geometry.find((geometry) => geometry.id === constraint.second.geometryId)
    const boundary = snapshot.geometry.find((geometry) => geometry.id === constraint.boundaryGeometryId)
    if (!first || !second || !boundary || first.type !== 'line' || second.type !== 'line' || boundary.type !== 'line' || new Set([first.id, second.id, boundary.id]).size !== 3) throw new PlanegcsSubsetError('Native planegcs SnellsLaw subset requires three distinct Line geometries.')
    const coincidentMatches = (samePointRef(coincident[0].first, constraint.first) && samePointRef(coincident[0].second, constraint.second)) || (samePointRef(coincident[0].first, constraint.second) && samePointRef(coincident[0].second, constraint.first))
    if (!coincidentMatches) throw new PlanegcsSubsetError('Native planegcs SnellsLaw Coincident prerequisite must connect the selected ray endpoints.')
    if (!samePointRef(pointOnBoundary[0].point, constraint.first) || pointOnBoundary[0].geometryId !== boundary.id) throw new PlanegcsSubsetError('Native planegcs SnellsLaw PointOnObject prerequisite must place the first ray endpoint on the boundary.')
    if (!module.solveSnellsLawLines) throw new PlanegcsSubsetError('Native planegcs SnellsLaw subset is unavailable in this module build.')
    const vector = module.solveSnellsLawLines(first.start.x, first.start.y, first.end.x, first.end.y, second.start.x, second.start.y, second.end.x, second.end.y, boundary.start.x, boundary.start.y, boundary.end.x, boundary.end.y, constraint.value, constraint.first.point === 'end', constraint.second.point === 'end')
    const values = readVector(vector, 14)
    const [solveStatus, firstStartX, firstStartY, firstEndX, firstEndY, secondStartX, secondStartY, secondEndX, secondEndY, boundaryStartX, boundaryStartY, boundaryEndX, boundaryEndY, residual] = values
    first.start = { x: firstStartX, y: firstStartY }
    first.end = { x: firstEndX, y: firstEndY }
    second.start = { x: secondStartX, y: secondStartY }
    second.end = { x: secondEndX, y: secondEndY }
    boundary.start = { x: boundaryStartX, y: boundaryStartY }
    boundary.end = { x: boundaryEndX, y: boundaryEndY }
    return resultFor(snapshot, solveStatus, Math.abs(residual), 8)
  }
  const internalAlignments = driving.filter((constraint): constraint is Extract<SketchConstraint, { type: 'internalAlignment' }> => constraint.type === 'internalAlignment')
  if (snapshot.geometry.length === 1 && internalAlignments.length > 0 && driving.length === internalAlignments.length) {
    const ellipse = snapshot.geometry[0]
    if (ellipse.type !== 'ellipse') throw new PlanegcsSubsetError('Native planegcs InternalAlignment subset supports Ellipse helper geometry only.')
    if (!module.solveEllipseInternalAlignment) throw new PlanegcsSubsetError('Native planegcs Ellipse InternalAlignment subset is unavailable in this module build.')
    const alignmentKeys = new Set(internalAlignments.map((constraint) => `${constraint.alignmentType}:${constraint.internalGeometryIndex}`))
    const quartetKeys = ['ellipse-major:0', 'ellipse-minor:0', 'ellipse-focus:0', 'ellipse-focus:1']
    if (internalAlignments.length === 4 && quartetKeys.every((key) => alignmentKeys.has(key))) {
      if (internalAlignments.some((constraint) => constraint.geometryId !== ellipse.id)) throw new PlanegcsSubsetError('Native planegcs Ellipse InternalAlignment must reference its single geometry.')
      if (!module.solveEllipseInternalAlignmentSet) throw new PlanegcsSubsetError('Native planegcs Ellipse InternalAlignment quartet is unavailable in this module build.')
      const vector = module.solveEllipseInternalAlignmentSet(ellipse.center.x, ellipse.center.y, ellipse.majorRadius, ellipse.minorRadius, ellipse.rotation)
      const values = readVector(vector, 10)
      const [solveStatus, centerX, centerY, focusX, focusY, minorRadius, ...alignmentResiduals] = values
      const focalDistance = Math.hypot(focusX - centerX, focusY - centerY)
      const solvedMajorRadius = Math.hypot(focalDistance, minorRadius)
      const solvedRotation = Math.atan2(focusY - centerY, focusX - centerX)
      if (Math.abs(centerX - ellipse.center.x) > 1e-7 || Math.abs(centerY - ellipse.center.y) > 1e-7 || Math.abs(solvedMajorRadius - ellipse.majorRadius) > 1e-7 || Math.abs(minorRadius - ellipse.minorRadius) > 1e-7 || Math.abs(solvedRotation - ellipse.rotation) > 1e-7) throw new Error('FreeCAD planegcs Ellipse InternalAlignment quartet unexpectedly changed its parent geometry.')
      return resultFor(snapshot, solveStatus, Math.max(...alignmentResiduals.map(Math.abs)), 5)
    }
    let solveStatus = 0
    let residual = 0
    for (const constraint of internalAlignments) {
      if (constraint.geometryId !== ellipse.id) throw new PlanegcsSubsetError('Native planegcs Ellipse InternalAlignment must reference its single geometry.')
      const alignmentType = constraint.alignmentType === 'ellipse-major' && constraint.internalGeometryIndex === 0 ? 1
        : constraint.alignmentType === 'ellipse-minor' && constraint.internalGeometryIndex === 0 ? 2
          : constraint.alignmentType === 'ellipse-focus' && constraint.internalGeometryIndex === 0 ? 3
            : constraint.alignmentType === 'ellipse-focus' && constraint.internalGeometryIndex === 1 ? 4
              : undefined
      if (alignmentType === undefined) throw new PlanegcsSubsetError('Native planegcs Ellipse InternalAlignment supports major/minor index 0 and focus indexes 0 or 1.')
      const vector = module.solveEllipseInternalAlignment(ellipse.center.x, ellipse.center.y, ellipse.majorRadius, ellipse.minorRadius, ellipse.rotation, alignmentType)
      const values = readVector(vector, 11)
      const [currentStatus, centerX, centerY, focusX, focusY, minorRadius, , , , , currentResidual] = values
      const focalDistance = Math.hypot(focusX - centerX, focusY - centerY)
      const solvedMajorRadius = Math.hypot(focalDistance, minorRadius)
      const solvedRotation = Math.atan2(focusY - centerY, focusX - centerX)
      if (Math.abs(centerX - ellipse.center.x) > 1e-7 || Math.abs(centerY - ellipse.center.y) > 1e-7 || Math.abs(solvedMajorRadius - ellipse.majorRadius) > 1e-7 || Math.abs(minorRadius - ellipse.minorRadius) > 1e-7 || Math.abs(solvedRotation - ellipse.rotation) > 1e-7) throw new Error('FreeCAD planegcs Ellipse InternalAlignment unexpectedly changed its parent geometry.')
      solveStatus = Math.max(solveStatus, currentStatus)
      residual = Math.max(residual, Math.abs(currentResidual))
    }
    return resultFor(snapshot, solveStatus, residual, 5)
  }
  const weights = driving.filter((constraint): constraint is Extract<SketchConstraint, { type: 'weight' }> => constraint.type === 'weight')
  if (snapshot.geometry.length === 1 && weights.length === 1 && (driving.length === 1 || driving.length === 2)) {
    const bspline = snapshot.geometry[0]
    const constraint = weights[0]
    if (bspline.type !== 'bspline' || constraint.geometryId !== bspline.id) throw new PlanegcsSubsetError('Native planegcs Weight subset requires one referenced B-spline.')
    const clampedKnots = bspline.knots?.length === 8 && bspline.knots.every((knot, index) => Math.abs(knot - (index < 4 ? 0 : 1)) <= 1e-12)
    if (bspline.degree !== 3 || bspline.controlPoints.length !== 4 || bspline.weights?.length !== 4 || !clampedKnots || bspline.periodic === true) throw new PlanegcsSubsetError('Native planegcs Weight subset requires four control points, four weights, clamped 0/1 knots, degree 3 and non-periodic mode.')
    if (!Number.isSafeInteger(constraint.controlPointIndex) || constraint.controlPointIndex < 0 || constraint.controlPointIndex >= 4 || !Number.isFinite(constraint.value) || !(constraint.value > 0)) throw new PlanegcsSubsetError('Native planegcs Weight requires a valid control-point index and positive finite value.')
    if (driving.length === 2) {
      const alignment = internalAlignments[0]
      if (internalAlignments.length !== 1 || alignment.geometryId !== bspline.id || alignment.alignmentType !== 'bspline-control-point' || alignment.internalGeometryIndex !== constraint.controlPointIndex) throw new PlanegcsSubsetError('Native planegcs Weight compound graph requires the matching B-spline control-point InternalAlignment.')
    }
    if (!module.solveCubicBsplineWeight) throw new PlanegcsSubsetError('Native planegcs B-spline Weight subset is unavailable in this module build.')
    const [pole0, pole1, pole2, pole3] = bspline.controlPoints
    const [weight0, weight1, weight2, weight3] = bspline.weights
    const vector = module.solveCubicBsplineWeight(pole0.x, pole0.y, pole1.x, pole1.y, pole2.x, pole2.y, pole3.x, pole3.y, weight0, weight1, weight2, weight3, constraint.controlPointIndex, constraint.value)
    const values = readVector(vector, 10)
    const [solveStatus, solvedWeight0, solvedWeight1, solvedWeight2, solvedWeight3, helperCenterX, helperCenterY, helperRadius, alignmentResidual, weightResidual] = values
    const selectedPole = bspline.controlPoints[constraint.controlPointIndex]
    if (Math.abs(helperCenterX - selectedPole.x) > 1e-7 || Math.abs(helperCenterY - selectedPole.y) > 1e-7 || Math.abs(helperRadius - constraint.value) > 1e-7) throw new Error('FreeCAD planegcs B-spline Weight returned an invalid control-point helper.')
    bspline.weights = [solvedWeight0, solvedWeight1, solvedWeight2, solvedWeight3]
    return resultFor(snapshot, solveStatus, Math.max(Math.abs(alignmentResidual), Math.abs(weightResidual)), 11)
  }
  const pointOnObject = driving.filter((constraint): constraint is Extract<SketchConstraint, { type: 'pointOnObject' }> => constraint.type === 'pointOnObject')
  if (snapshot.geometry.length === 2 && driving.length === 1 && pointOnObject.length === 1) {
    const constraint = pointOnObject[0]
    if (constraint.point.point !== 'position') throw new PlanegcsSubsetError('Native planegcs PointOnObject subset requires a Point position reference.')
    const point = snapshot.geometry.find((geometry) => geometry.id === constraint.point.geometryId)
    const target = snapshot.geometry.find((geometry) => geometry.id === constraint.geometryId)
    if (!point || !target || point.type !== 'point' || point.id === target.id) throw new PlanegcsSubsetError('Native planegcs PointOnObject subset requires one distinct Point and target geometry.')
    if (target.type === 'line') {
      const dx = target.end.x - target.start.x
      const dy = target.end.y - target.start.y
      const vertical = Math.abs(dx) <= 1e-12 && Math.abs(dy) > 1e-12
      const horizontal = Math.abs(dy) <= 1e-12 && Math.abs(dx) > 1e-12
      if (!horizontal && !vertical) throw new PlanegcsSubsetError('Native planegcs PointOnObject subset requires a horizontal or vertical non-degenerate Line.')
      if (!module.solvePointOnLine) throw new PlanegcsSubsetError('Native planegcs PointOnObject line subset is unavailable in this module build.')
      const vector = module.solvePointOnLine(point.position.x, point.position.y, target.start.x, target.start.y, target.end.x, target.end.y, vertical)
      const values = readVector(vector, 8)
      const [solveStatus, pointX, pointY, startX, startY, endX, endY, residual] = values
      point.position = { x: pointX, y: pointY }
      target.start = { x: startX, y: startY }
      target.end = { x: endX, y: endY }
      return resultFor(snapshot, solveStatus, Math.abs(residual), 0)
    }
    if (target.type === 'circle') {
      if (!(target.radius > 0)) throw new PlanegcsSubsetError('Native planegcs PointOnObject Circle requires a positive radius.')
      if (!module.solvePointOnCircle) throw new PlanegcsSubsetError('Native planegcs PointOnObject circle subset is unavailable in this module build.')
      const vector = module.solvePointOnCircle(point.position.x, point.position.y, target.center.x, target.center.y, target.radius)
      const values = readVector(vector, 7)
      const [solveStatus, pointX, pointY, centerX, centerY, radius, residual] = values
      point.position = { x: pointX, y: pointY }
      target.center = { x: centerX, y: centerY }
      target.radius = radius
      return resultFor(snapshot, solveStatus, Math.abs(residual), 0)
    }
    if (target.type === 'arc') {
      if (!(target.radius > 0) || !Number.isFinite(target.startAngle) || !Number.isFinite(target.endAngle)) throw new PlanegcsSubsetError('Native planegcs PointOnObject Arc requires a positive radius and finite angles.')
      if (!module.solvePointOnArc) throw new PlanegcsSubsetError('Native planegcs PointOnObject arc subset is unavailable in this module build.')
      const vector = module.solvePointOnArc(point.position.x, point.position.y, target.center.x, target.center.y, target.radius, target.startAngle, target.endAngle)
      const values = readVector(vector, 9)
      const [solveStatus, pointX, pointY, centerX, centerY, radius, startAngle, endAngle, residual] = values
      const tau = Math.PI * 2
      const normalized = (angle: number) => ((angle % tau) + tau) % tau
      const sweep = normalized(endAngle - startAngle)
      const position = normalized(Math.atan2(pointY - centerY, pointX - centerX) - startAngle)
      if (sweep <= 1e-12 || position > sweep + 1e-9) throw new PlanegcsSubsetError('Native planegcs PointOnObject arc solution lies outside the target sweep.')
      point.position = { x: pointX, y: pointY }
      target.center = { x: centerX, y: centerY }
      target.radius = radius
      target.startAngle = startAngle
      target.endAngle = endAngle
      return resultFor(snapshot, solveStatus, Math.abs(residual), 0)
    }
    if (target.type === 'bspline') {
      const unitWeights = target.weights === undefined || target.weights.every((weight) => Math.abs(weight - 1) <= 1e-12)
      const clampedKnots = target.knots === undefined || (target.knots.length === 8 && target.knots.every((knot, index) => Math.abs(knot - (index < 4 ? 0 : 1)) <= 1e-12))
      const monotonicX = target.controlPoints.every((controlPoint, index) => index === 0 || controlPoint.x > target.controlPoints[index - 1].x)
      if (target.degree !== 3 || target.controlPoints.length !== 4 || target.periodic === true || !unitWeights || !clampedKnots || !monotonicX) throw new PlanegcsSubsetError('Native planegcs PointOnObject B-spline requires four strictly X-monotonic cubic control points, unit weights, clamped 0/1 knots and non-periodic mode.')
      const [pole0, pole1, pole2, pole3] = target.controlPoints
      if (point.position.x < pole0.x - 1e-12 || point.position.x > pole3.x + 1e-12) throw new PlanegcsSubsetError('Native planegcs PointOnObject B-spline requires the fixed point X within the curve endpoint range.')
      if (!module.solvePointOnCubicBspline) throw new PlanegcsSubsetError('Native planegcs PointOnObject B-spline subset is unavailable in this module build.')
      const initialParameter = (point.position.x - pole0.x) / (pole3.x - pole0.x)
      const vector = module.solvePointOnCubicBspline(point.position.x, point.position.y, pole0.x, pole0.y, pole1.x, pole1.y, pole2.x, pole2.y, pole3.x, pole3.y, initialParameter)
      const values = readVector(vector, 6)
      const [solveStatus, pointX, pointY, pointParameter, residualX, residualY] = values
      if (pointParameter < -1e-9 || pointParameter > 1 + 1e-9) throw new PlanegcsSubsetError('Native planegcs PointOnObject B-spline solution lies outside the clamped parameter range.')
      point.position = { x: pointX, y: pointY }
      return resultFor(snapshot, solveStatus, Math.max(Math.abs(residualX), Math.abs(residualY)), 0)
    }
    if (target.type !== 'ellipse' || !(target.majorRadius > target.minorRadius) || !(target.minorRadius > 0) || !Number.isFinite(target.rotation)) throw new PlanegcsSubsetError('Native planegcs PointOnObject subset supports only a valid Circle, Arc, Ellipse or horizontal/vertical Line.')
    if (!module.solvePointOnEllipse) throw new PlanegcsSubsetError('Native planegcs PointOnObject ellipse subset is unavailable in this module build.')
    const focalDistance = Math.sqrt(Math.max(0, target.majorRadius * target.majorRadius - target.minorRadius * target.minorRadius))
    const focusX = target.center.x + focalDistance * Math.cos(target.rotation)
    const focusY = target.center.y + focalDistance * Math.sin(target.rotation)
    const vector = module.solvePointOnEllipse(point.position.x, point.position.y, target.center.x, target.center.y, focusX, focusY, target.minorRadius)
    const values = readVector(vector, 9)
    const [solveStatus, pointX, pointY, centerX, centerY, solvedFocusX, solvedFocusY, minorRadius, residual] = values
    point.position = { x: pointX, y: pointY }
    target.center = { x: centerX, y: centerY }
    target.minorRadius = minorRadius
    const solvedFocalDistance = Math.hypot(solvedFocusX - centerX, solvedFocusY - centerY)
    target.majorRadius = Math.hypot(solvedFocalDistance, minorRadius)
    target.rotation = Math.atan2(solvedFocusY - centerY, solvedFocusX - centerX)
    return resultFor(snapshot, solveStatus, Math.abs(residual), 0)
  }
  if (snapshot.geometry.length === 1 && snapshot.geometry[0].type === 'circle') {
    const circle = snapshot.geometry[0]
    const dimensions = driving.filter((constraint): constraint is Extract<SketchConstraint, { type: 'radius' | 'diameter' }> => (constraint.type === 'radius' || constraint.type === 'diameter') && constraint.geometryId === circle.id)
    if (driving.length !== 1 || dimensions.length !== 1 || !Number.isFinite(dimensions[0].value) || dimensions[0].value <= 0) throw new PlanegcsSubsetError('Native planegcs circle subset requires one driving positive Radius or Diameter constraint.')
    const dimension = dimensions[0]
    const vector = dimension.type === 'diameter'
      ? module.solveCircleDiameter(circle.center.x, circle.center.y, circle.radius, dimension.value)
      : module.solveCircleRadius(circle.center.x, circle.center.y, circle.radius, dimension.value)
    const values = readVector(vector, 5)
    const [solveStatus, centerX, centerY, radius, residual] = values
    circle.center = { x: centerX, y: centerY }
    circle.radius = radius
    return resultFor(snapshot, solveStatus, Math.abs(residual), 0)
  }
  if (snapshot.geometry.length === 1 && snapshot.geometry[0].type === 'line') {
    const line = snapshot.geometry[0]
    const orientations = driving.filter((constraint) => (constraint.type === 'horizontal' || constraint.type === 'vertical') && constraint.geometryId === line.id)
    const distances = driving.filter((constraint) => isLineEndpointDistance(constraint, line.id))
    const angles = driving.filter((constraint): constraint is Extract<SketchConstraint, { type: 'angle' }> => constraint.type === 'angle' && constraint.geometryId === line.id)
    if (driving.length !== 2 || distances.length !== 1 || (orientations.length + angles.length) !== 1) throw new PlanegcsSubsetError('Native planegcs one-line subset requires one driving orientation or Angle and one driving endpoint Distance, DistanceX or DistanceY constraint.')
    const distanceConstraint = distances[0]
    if ((distanceConstraint.type !== 'distance' && distanceConstraint.type !== 'distanceX' && distanceConstraint.type !== 'distanceY') || !Number.isFinite(distanceConstraint.value) || distanceConstraint.value <= 0) throw new PlanegcsSubsetError('Native planegcs endpoint Distance must be finite and greater than zero.')
    if (angles.length === 1) {
      if (distanceConstraint.type !== 'distance' || !Number.isFinite(angles[0].value)) throw new PlanegcsSubsetError('Native planegcs Angle requires a driving endpoint Distance and a finite angle in radians.')
      const vector = module.solveAngle(line.start.x, line.start.y, line.end.x, line.end.y, distanceConstraint.value, angles[0].value)
      const values = readVector(vector, 7)
      const [solveStatus, startX, startY, endX, endY, lengthResidual, angleResidual] = values
      line.start = { x: startX, y: startY }
      line.end = { x: endX, y: endY }
      return resultFor(snapshot, solveStatus, Math.max(Math.abs(lengthResidual), Math.abs(angleResidual)), 0)
    }
    const orientation = orientations[0]
    const vector = distanceConstraint.type === 'distanceX'
      ? orientation.type === 'horizontal'
        ? module.solveDistanceX(line.start.x, line.start.y, line.end.x, line.end.y, distanceConstraint.value)
        : (() => { throw new PlanegcsSubsetError('Native planegcs DistanceX requires a driving Horizontal constraint.') })()
      : distanceConstraint.type === 'distanceY'
        ? orientation.type === 'vertical'
          ? module.solveDistanceY(line.start.x, line.start.y, line.end.x, line.end.y, distanceConstraint.value)
          : (() => { throw new PlanegcsSubsetError('Native planegcs DistanceY requires a driving Vertical constraint.') })()
      : orientation.type === 'vertical'
        ? module.solveVerticalDistance(line.start.x, line.start.y, line.end.x, line.end.y, distanceConstraint.value)
        : module.solveHorizontalDistance(line.start.x, line.start.y, line.end.x, line.end.y, distanceConstraint.value)
    const values = readVector(vector, 6)
    const [solveStatus, startX, startY, endX, endY, signedResidual] = values
    line.start = { x: startX, y: startY }
    line.end = { x: endX, y: endY }
    return resultFor(snapshot, solveStatus, Math.abs(signedResidual), 2)
  }
  const equal = driving.filter((constraint): constraint is Extract<SketchConstraint, { type: 'equal' }> => constraint.type === 'equal')
  const tangent = driving.filter((constraint): constraint is Extract<SketchConstraint, { type: 'tangent' }> => constraint.type === 'tangent')
  if (driving.length === 1 && tangent.length === 1) {
    const constraint = tangent[0]
    const first = snapshot.geometry.find((geometry) => geometry.id === constraint.firstGeometryId)
    const second = snapshot.geometry.find((geometry) => geometry.id === constraint.secondGeometryId)
    if (!first || !second || first.id === second.id || first.type !== 'circle' || second.type !== 'circle') throw new PlanegcsSubsetError('Native planegcs Tangent subset supports two distinct circles only.')
    const vector = module.solveTangentCircles(first.center.x, first.center.y, first.radius, second.center.x, second.center.y, second.radius)
    const values = readVector(vector, 8)
    const [solveStatus, firstCenterX, firstCenterY, firstRadius, secondCenterX, secondCenterY, secondRadius, residual] = values
    first.center = { x: firstCenterX, y: firstCenterY }
    first.radius = firstRadius
    second.center = { x: secondCenterX, y: secondCenterY }
    second.radius = secondRadius
    return resultFor(snapshot, solveStatus, Math.abs(residual), 0)
  }
  if (driving.length === 1 && equal.length === 1) {
    const constraint = equal[0]
    const first = snapshot.geometry.find((geometry) => geometry.id === constraint.firstGeometryId)
    const second = snapshot.geometry.find((geometry) => geometry.id === constraint.secondGeometryId)
    if (!first || !second || first.id === second.id) throw new PlanegcsSubsetError('Native planegcs Equal constraint must reference two distinct geometries.')
    if (first.type === 'line' && second.type === 'line') {
      const vector = module.solveEqualLines(first.start.x, first.start.y, first.end.x, first.end.y, second.start.x, second.start.y, second.end.x, second.end.y)
      const values = readVector(vector, 10)
      const [solveStatus, firstStartX, firstStartY, firstEndX, firstEndY, secondStartX, secondStartY, secondEndX, secondEndY, residual] = values
      first.start = { x: firstStartX, y: firstStartY }
      first.end = { x: firstEndX, y: firstEndY }
      second.start = { x: secondStartX, y: secondStartY }
      second.end = { x: secondEndX, y: secondEndY }
      return resultFor(snapshot, solveStatus, Math.abs(residual), 1)
    }
    if (first.type === 'circle' && second.type === 'circle') {
      const vector = module.solveEqualCircles(first.center.x, first.center.y, first.radius, second.center.x, second.center.y, second.radius)
      const values = readVector(vector, 8)
      const [solveStatus, firstCenterX, firstCenterY, firstRadius, secondCenterX, secondCenterY, secondRadius, residual] = values
      first.center = { x: firstCenterX, y: firstCenterY }
      first.radius = firstRadius
      second.center = { x: secondCenterX, y: secondCenterY }
      second.radius = secondRadius
      return resultFor(snapshot, solveStatus, Math.abs(residual), 0)
    }
    throw new PlanegcsSubsetError('Native planegcs Equal subset supports two lines or two circles only.')
  }
  if (snapshot.geometry.length !== 2 || snapshot.geometry.some((geometry) => geometry.type !== 'line')) throw new PlanegcsSubsetError('Native planegcs subset requires one or two lines.')
  const coincident = driving.filter((constraint) => constraint.type === 'coincident')
  if (driving.length === 1 && coincident.length === 1) {
    const constraint = coincident[0]
    const first = snapshot.geometry.find((geometry) => geometry.id === constraint.first.geometryId)
    const second = snapshot.geometry.find((geometry) => geometry.id === constraint.second.geometryId)
    if (!first || !second || first.type !== 'line' || second.type !== 'line' || first.id === second.id) throw new PlanegcsSubsetError('Native planegcs coincident constraint must reference two distinct lines.')
    if ((constraint.first.point !== 'start' && constraint.first.point !== 'end') || (constraint.second.point !== 'start' && constraint.second.point !== 'end')) throw new PlanegcsSubsetError('Native planegcs coincident constraint requires start or end references on both lines.')
    const secondLength = Math.hypot(second.end.x - second.start.x, second.end.y - second.start.y)
    if (!(secondLength > 0)) throw new PlanegcsSubsetError('Native planegcs coincident constraint requires a non-degenerate second line.')
    const args = [first.start.x, first.start.y, first.end.x, first.end.y, second.start.x, second.start.y, second.end.x, second.end.y, secondLength] as const
    const vector = module.solveCoincidentLinePoints
      ? module.solveCoincidentLinePoints(...args, constraint.first.point === 'end', constraint.second.point === 'end')
      : constraint.first.point === 'end' && constraint.second.point === 'start'
        ? module.solveCoincidentLines(...args)
        : (() => { throw new PlanegcsSubsetError('Native planegcs artifact does not expose selectable Coincident line endpoints.') })()
    const values = readVector(vector, 10)
    const [solveStatus, firstStartX, firstStartY, firstEndX, firstEndY, secondStartX, secondStartY, secondEndX, secondEndY, residual] = values
    first.start = { x: firstStartX, y: firstStartY }
    first.end = { x: firstEndX, y: firstEndY }
    second.start = { x: secondStartX, y: secondStartY }
    second.end = { x: secondEndX, y: secondEndY }
    return resultFor(snapshot, solveStatus, Math.abs(residual), 1)
  }
  const relations = driving.filter((constraint) => constraint.type === 'parallel' || constraint.type === 'perpendicular')
  if (driving.length !== 1 || relations.length !== 1) throw new PlanegcsSubsetError('Native planegcs two-line subset requires exactly one driving Parallel, Perpendicular or Coincident constraint.')
  const relation = relations[0]
  if (relation.type !== 'parallel' && relation.type !== 'perpendicular') throw new PlanegcsSubsetError('Native planegcs line relation is invalid.')
  const first = snapshot.geometry.find((geometry) => geometry.id === relation.firstGeometryId)
  const second = snapshot.geometry.find((geometry) => geometry.id === relation.secondGeometryId)
  if (!first || !second || first.type !== 'line' || second.type !== 'line' || first.id === second.id) throw new PlanegcsSubsetError('Native planegcs line relation must reference two distinct lines in the snapshot.')
  const secondLength = Math.hypot(second.end.x - second.start.x, second.end.y - second.start.y)
  if (!(secondLength > 0)) throw new PlanegcsSubsetError('Native planegcs line relation requires a non-degenerate second line.')
  const args = [first.start.x, first.start.y, first.end.x, first.end.y, second.start.x, second.start.y, second.end.x, second.end.y, secondLength] as const
  const vector = relation.type === 'perpendicular' ? module.solvePerpendicularLines(...args) : module.solveParallelLines(...args)
  const values = readVector(vector, 10)
  const [solveStatus, firstStartX, firstStartY, firstEndX, firstEndY, secondStartX, secondStartY, secondEndX, secondEndY, signedResidual] = values
  first.start = { x: firstStartX, y: firstStartY }
  first.end = { x: firstEndX, y: firstEndY }
  second.start = { x: secondStartX, y: secondStartY }
  second.end = { x: secondEndX, y: secondEndY }
  return resultFor(snapshot, solveStatus, Math.abs(signedResidual), 7)
}

const readVector = (vector: PlanegcsDoubleVector, expectedSize: number): number[] => {
  let values: number[]
  try {
    if (vector.size() !== expectedSize) throw new Error(`FreeCAD planegcs returned ${vector.size()} values; expected ${expectedSize}.`)
    values = Array.from({ length: expectedSize }, (_, index) => vector.get(index))
  } finally {
    vector.delete()
  }
  if (values.some((value) => !Number.isFinite(value))) throw new Error('FreeCAD planegcs returned a non-finite solution.')
  return values
}

const resultFor = (snapshot: SketchSnapshot, solveStatus: number, residual: number, degreesOfFreedom: number): SketchSolveResult => {
  const converged = solveStatus <= 1
  const diagnostics = converged ? [] : [{ code: 'SOLVER_NOT_CONVERGED' as const, message: `FreeCAD planegcs solve status ${solveStatus}.` }]
  const status = converged ? (degreesOfFreedom === 0 ? 'solved' as const : 'under-constrained' as const) : 'conflicting' as const
  snapshot.solver = { status, degreesOfFreedom, residual, iterations: 0, diagnostics }
  return { snapshot, status, degreesOfFreedom, residual, iterations: 0, diagnostics }
}
