import {
  armRestCandidateStatus,
  armRestMotionGateStatus,
  kaguraRuntimeOutcomeStatus,
  kaguraRuntimeShouldFail,
  poseMismatchWarningIds,
  poseNormalizationCandidateSpecs,
  qualityCompareMetricStatus,
  qualityComparisonDecision,
  qualityFootContactVerdict,
  qualityGroundVerdict,
  qualityLimbExtentVerdict,
  qualityRenderVerifyVerdict,
  qualitySummaryVerdict,
  qualityVerdictScore,
  retargetStrictVerdict,
  robotVoxelRetargetRuleId,
  robotVoxelRetargetScore,
  robotVoxelRetargetVerdict,
  rootTranslationCandidateId,
  rootTranslationRecommendationId,
  selectCandidateGroup,
  motionCorePolicy,
} from "./motion-core-runtime.mjs";

const cases = [
  ["arm-rest-gate null", () => armRestMotionGateStatus(null), "unavailable"],
  ["arm-rest-gate 14.48395", () => armRestMotionGateStatus(14.48395), "blocked"],
  ["arm-rest-gate 60", () => armRestMotionGateStatus(60), "passed"],
  [
    "arm-rest-candidate 14.48395",
    () => armRestCandidateStatus(14.48395),
    "needs-motion-evidence",
  ],
  ["arm-rest-candidate 108.40739", () => armRestCandidateStatus(108.40739), "runnable"],
  [
    "select-candidate-group needs-policy",
    () => selectCandidateGroup(false, {
      candidateImproved: 1,
      candidateRegressed: 0,
      candidateTradeoff: 0,
      stable: 0,
      missingComparison: 0,
      missingSampleComparison: 0,
    }),
    "needs-policy",
  ],
  [
    "select-candidate-group accepted",
    () => selectCandidateGroup(true, {
      candidateImproved: 1,
      candidateRegressed: 0,
      candidateTradeoff: 0,
      stable: 0,
      missingComparison: 0,
      missingSampleComparison: 0,
    }),
    "accepted",
  ],
  [
    "select-candidate-group rejected",
    () => selectCandidateGroup(false, {
      candidateImproved: 0,
      candidateRegressed: 1,
      candidateTradeoff: 0,
      stable: 0,
      missingComparison: 0,
      missingSampleComparison: 0,
    }),
    "rejected",
  ],
  [
    "select-candidate-group promotable",
    () => selectCandidateGroup(false, {
      candidateImproved: 2,
      candidateRegressed: 0,
      candidateTradeoff: 0,
      stable: 1,
      missingComparison: 0,
      missingSampleComparison: 0,
    }),
    "promotable",
  ],
  [
    "select-candidate-group stable-only",
    () => selectCandidateGroup(false, {
      candidateImproved: 0,
      candidateRegressed: 0,
      candidateTradeoff: 0,
      stable: 3,
      missingComparison: 0,
      missingSampleComparison: 0,
    }),
    "neutral",
  ],
  [
    "select-candidate-group missing-comparison",
    () => selectCandidateGroup(false, {
      candidateImproved: 0,
      candidateRegressed: 0,
      candidateTradeoff: 0,
      stable: 0,
      missingComparison: 1,
      missingSampleComparison: 0,
    }),
    "missing-comparison",
  ],
  [
    "root-translation-recommendation unavailable",
    () => rootTranslationRecommendationId({
      mode: "relative",
      heightScale: null,
      heightScaleDelta: 0.3,
      verticalDeltaRange: 0.2,
    }),
    "height-scale-unavailable",
  ],
  [
    "root-translation-recommendation relative candidate",
    () => rootTranslationRecommendationId({
      mode: "relative",
      heightScale: 0.6,
      heightScaleDelta: 0.2,
      verticalDeltaRange: 0.08,
    }),
    "consider-scale-to-model",
  ],
  [
    "root-translation-recommendation relative ok",
    () => rootTranslationRecommendationId({
      mode: "relative",
      heightScale: 0.6,
      heightScaleDelta: 0.2,
      verticalDeltaRange: 0.079,
    }),
    "relative-ok",
  ],
  [
    "root-translation-recommendation horizontal dropped",
    () => rootTranslationRecommendationId({
      mode: "horizontal-only",
      heightScale: 0.6,
      heightScaleDelta: 0.2,
      verticalDeltaRange: 0.08,
    }),
    "vertical-motion-dropped",
  ],
  [
    "root-translation-candidate scale",
    () => rootTranslationCandidateId("consider-scale-to-model"),
    "root-scale-to-model",
  ],
  [
    "root-translation-candidate relative",
    () => rootTranslationCandidateId("vertical-motion-dropped"),
    "root-relative",
  ],
  [
    "root-translation-candidate none",
    () => rootTranslationCandidateId("relative-ok"),
    "none",
  ],
  [
    "pose-mismatch-warning-ids all",
    () => poseMismatchWarningIds({
      scaleSpreadRatio: 1.25,
      footSpreadScale: 2.0,
      upperLegSpreadScale: 0.5,
      shoulderWidthScale: 1.6,
      skeletonHeightScale: 1.0,
      armAngleDeltaDeg: 45.0,
    }).join("|"),
    "scale-inconsistent|foot-spread-mismatch|leg-spread-mismatch|shoulder-width-mismatch|arm-rest-angle-mismatch",
  ],
  [
    "pose-mismatch-warning-ids none",
    () => poseMismatchWarningIds({
      scaleSpreadRatio: 1.249,
      footSpreadScale: 1.999,
      upperLegSpreadScale: 0.501,
      shoulderWidthScale: 1.39,
      skeletonHeightScale: 1.0,
      armAngleDeltaDeg: 44.9,
    }).join("|"),
    "",
  ],
  [
    "pose-mismatch-warning-ids missing reference",
    () => poseMismatchWarningIds({
      scaleSpreadRatio: null,
      footSpreadScale: null,
      upperLegSpreadScale: null,
      shoulderWidthScale: 1.6,
      skeletonHeightScale: null,
      armAngleDeltaDeg: null,
    }).join("|"),
    "",
  ],
  [
    "pose-normalization-candidate-specs all",
    () => formatCandidateSpecs(poseNormalizationCandidateSpecs({
      hasArmRestAngleMismatch: true,
      hasFootSpreadMismatch: true,
      hasLegSpreadMismatch: true,
      hasShoulderWidthMismatch: true,
      maxUpperArmRotationRangeDeg: 108.40739,
    })),
    "arm-rest-pose-offset:runnable|stance-width-adapter:runnable|shoulder-width-adapter:review-target-rig",
  ],
  [
    "pose-normalization-candidate-specs arm blocked",
    () => formatCandidateSpecs(poseNormalizationCandidateSpecs({
      hasArmRestAngleMismatch: true,
      hasFootSpreadMismatch: false,
      hasLegSpreadMismatch: false,
      hasShoulderWidthMismatch: false,
      maxUpperArmRotationRangeDeg: 14.48395,
    })),
    "arm-rest-pose-offset:needs-motion-evidence",
  ],
  [
    "pose-normalization-candidate-specs lower body",
    () => formatCandidateSpecs(poseNormalizationCandidateSpecs({
      hasArmRestAngleMismatch: false,
      hasFootSpreadMismatch: false,
      hasLegSpreadMismatch: true,
      hasShoulderWidthMismatch: false,
      maxUpperArmRotationRangeDeg: null,
    })),
    "stance-width-adapter:runnable",
  ],
  [
    "policy.root.recommendationId",
    () => motionCorePolicy.root.recommendationId({
      mode: "relative",
      heightScale: 0.6,
      heightScaleDelta: 0.2,
      verticalDeltaRange: 0.08,
    }),
    "consider-scale-to-model",
  ],
  [
    "policy.root.candidateId",
    () => motionCorePolicy.root.candidateId("vertical-motion-dropped"),
    "root-relative",
  ],
  [
    "policy.pose.armRestMotionGateStatus",
    () => motionCorePolicy.pose.armRestMotionGateStatus(108.40739),
    "passed",
  ],
  [
    "policy.pose.mismatchWarningIds",
    () => motionCorePolicy.pose.mismatchWarningIds({
      scaleSpreadRatio: null,
      footSpreadScale: 2.0,
      upperLegSpreadScale: null,
      shoulderWidthScale: null,
      skeletonHeightScale: null,
      armAngleDeltaDeg: null,
    }).join("|"),
    "foot-spread-mismatch",
  ],
  [
    "policy.pose.normalizationCandidateSpecs",
    () => formatCandidateSpecs(motionCorePolicy.pose.normalizationCandidateSpecs({
      hasArmRestAngleMismatch: true,
      hasFootSpreadMismatch: false,
      hasLegSpreadMismatch: false,
      hasShoulderWidthMismatch: false,
      maxUpperArmRotationRangeDeg: 108.40739,
    })),
    "arm-rest-pose-offset:runnable",
  ],
  [
    "policy.selection.candidateGroup",
    () => motionCorePolicy.selection.candidateGroup(false, {
      candidateImproved: 0,
      candidateRegressed: 0,
      candidateTradeoff: 1,
      missingComparison: 0,
      missingSampleComparison: 0,
    }),
    "rejected",
  ],
  [
    "retarget-strict-verdict pass",
    () => retargetStrictVerdict({
      trackCount: 6,
      skipped: 4,
      minRetainedRatioWarn: 0.4,
    }),
    "pass",
  ],
  [
    "retarget-strict-verdict warn",
    () => retargetStrictVerdict({
      trackCount: 2,
      skipped: 4,
      minRetainedRatioWarn: 0.4,
    }),
    "warn",
  ],
  [
    "robot-voxel-retarget-rule finger",
    () => robotVoxelRetargetRuleId("LeftThumbProximal skipped"),
    "finger",
  ],
  [
    "robot-voxel-retarget-rule fallback",
    () => robotVoxelRetargetRuleId("neck skipped"),
    "upper-body-fallback",
  ],
  [
    "robot-voxel-retarget-rule core",
    () => robotVoxelRetargetRuleId("leftUpperArm skipped"),
    "required-core",
  ],
  [
    "robot-voxel-retarget-score warn",
    () => String(robotVoxelRetargetScore(0.5)),
    "0.75",
  ],
  [
    "robot-voxel-retarget-verdict warn",
    () => robotVoxelRetargetVerdict({
      weightedPenalty: 0.5,
      hardFailureCount: 0,
    }),
    "warn",
  ],
  [
    "robot-voxel-retarget-verdict hard fail",
    () => robotVoxelRetargetVerdict({
      weightedPenalty: 0,
      hardFailureCount: 1,
    }),
    "fail",
  ],
  [
    "policy.retarget.robotVoxelRuleId",
    () => motionCorePolicy.retarget.robotVoxelRuleId("right foot skipped"),
    "required-core",
  ],
  [
    "policy.retarget.robotVoxelVerdict",
    () => motionCorePolicy.retarget.robotVoxelVerdict({
      weightedPenalty: 0,
      hardFailureCount: 0,
    }),
    "pass",
  ],
  [
    "quality-verdict-score pass",
    () => String(qualityVerdictScore("pass")),
    "3",
  ],
  [
    "quality-compare-metric-status lower improved",
    () => qualityCompareMetricStatus({
      baseline: 1.0,
      candidate: 0.98,
      tolerance: 0.01,
      better: "lower",
    }),
    "improved",
  ],
  [
    "quality-comparison-decision tradeoff",
    () => qualityComparisonDecision({
      improved: 1,
      regressed: 1,
    }),
    "candidate-tradeoff",
  ],
  [
    "quality-summary-verdict warn",
    () => qualitySummaryVerdict({
      failCount: 0,
      warnCount: 1,
    }),
    "warn",
  ],
  [
    "quality-render-verify-verdict missing",
    () => qualityRenderVerifyVerdict({
      hasReport: false,
      ok: false,
    }),
    "warn",
  ],
  [
    "quality-ground-verdict fail",
    () => qualityGroundVerdict({
      minGround: -2.6,
      warnThreshold: -0.35,
      failThreshold: -2.5,
    }),
    "fail",
  ],
  [
    "quality-foot-contact-verdict floating",
    () => qualityFootContactVerdict({
      contactCount: 2,
      minFootDeltaY: 0.66,
      sinkWarnThreshold: -0.25,
      alwaysFloatingWarnThreshold: 0.65,
    }),
    "warn",
  ],
  [
    "quality-limb-extent-verdict pass",
    () => qualityLimbExtentVerdict({
      displacementCount: 2,
      pelvis: 0.2,
      maxTrackedNode: 1.35,
      maxPelvisWarn: 0.45,
      maxTrackedNodeWarn: 1.35,
    }),
    "pass",
  ],
  [
    "policy.quality.compareMetricStatus",
    () => motionCorePolicy.quality.compareMetricStatus({
      baseline: 2,
      candidate: 1,
      tolerance: 0,
      better: "higher",
    }),
    "regressed",
  ],
  [
    "kagura-runtime-outcome-status environment",
    () => kaguraRuntimeOutcomeStatus({
      targetOk: false,
      calibrationOk: false,
    }),
    "environment-failed",
  ],
  [
    "kagura-runtime-should-fail allowed environment",
    () => String(kaguraRuntimeShouldFail("environment-failed", {
      allowEnvironmentFailure: true,
    })),
    "false",
  ],
  [
    "policy.kaguraRuntime.outcomeStatus",
    () => motionCorePolicy.kaguraRuntime.outcomeStatus({
      targetOk: false,
      calibrationOk: true,
    }),
    "asset-failed",
  ],
];

const failures = [];

for (const [label, evaluate, expected] of cases) {
  const actual = evaluate();
  if (actual !== expected) {
    failures.push(`${label}: expected ${expected}, got ${actual}`);
  }
}

if (failures.length > 0) {
  console.error(failures.join("\n"));
  process.exitCode = 1;
} else {
  console.log(`motion-core parity passed: ${cases.length} cases`);
}

function formatCandidateSpecs(specs) {
  return specs.map((spec) => `${spec.id}:${spec.status}`).join("|");
}
