import type { CanonicalBone, ColliderDef } from "@psx/shared";

/**
 * Content harness interfaces — GDD §10.4, Appendix C.
 *
 * The shipped Milestone 3 path is *code-drawn*, not a third-party mesh API:
 * reference image → silhouette → measurements → tubes on the canonical
 * skeleton → automatic skin weights → procedural clips → GLB. See
 * `pipeline.ts` / `pnpm harness`.
 *
 * These types remain for the broader GDD contract (props, colliders, future
 * alternate generators). Prefer `runPipeline` for characters.
 */

/** How the mesh was produced. `"code"` is the default harness path. */
export type MeshProvider = "code" | "meshy" | "triposr" | "img2threejs" | "mock";
export type MeshStyle = "realistic" | "lowpoly" | "psx";

export interface Img2MeshRequest {
  image: Buffer | string;
  style?: MeshStyle;
  provider?: MeshProvider;
  /** Target triangle budget after PSX decimation. */
  targetTriangles?: number;
}

export interface Img2MeshResult {
  glbPath: string;
  provider: MeshProvider;
  triangleCount: number;
  generationSeconds: number;
}

export interface RigResult {
  glbPath: string;
  /** Source rigger bone name → canonical bone name. */
  boneMap: Record<string, CanonicalBone>;
  /** Canonical bones the rigger could not produce. */
  missingBones: CanonicalBone[];
  /** Auto-generated collision, limited to shapes box3d-wasm actually binds. */
  colliders: ColliderDef[];
}

export interface AnimationClipResult {
  name: string;
  glbPath: string;
  durationSeconds: number;
  frameRate: number;
  /** Bones the clip actually animates; the rest fall back to bind pose. */
  animatedBones: CanonicalBone[];
}

export type AnimationSource = "pose" | "video" | "procedural";

export interface CharacterHarness {
  fromPhoto(
    image: Buffer | string,
    options?: Img2MeshRequest,
  ): Promise<{ mesh: RigResult; defaultPose?: AnimationClipResult }>;

  generateAnimation(from: AnimationSource, input: unknown): Promise<AnimationClipResult>;
}

/** Optional external mesh-provider plug-in (not used by the default pipeline). */
export interface MeshProviderAdapter {
  readonly name: MeshProvider;
  isConfigured(): boolean;
  generate(request: Img2MeshRequest): Promise<Img2MeshResult>;
}
