import type {
  BuiltInSpriteId,
  FieldId,
  JoanEngineOptions,
  PixelShape,
  PixelSwitch,
  SpriteRecipe,
  Transition,
} from "./index.js";

export interface ConfigurationIssue {
  code: string;
  message: string;
  path: string | null;
  value: unknown;
  suggestion: string | null;
  severity: "error";
}

export interface InspectEngineOptionsResult {
  ok: boolean;
  value: Partial<JoanEngineOptions> & Record<string, unknown>;
  issues: ConfigurationIssue[];
}

export interface InspectEngineOptionsSettings {
  coerce?: boolean;
  allowUnknown?: boolean;
}

export interface ValidateEngineOptionsSettings
  extends InspectEngineOptionsSettings {
  strict?: boolean;
}

export class JoanConfigurationError extends RangeError {
  readonly name: "JoanConfigurationError";
  readonly code: string;
  readonly path: string | null;
  readonly value: unknown;
  readonly suggestion: string | null;
  readonly allowed: unknown[] | null;
  constructor(
    message: string,
    details?: Partial<ConfigurationIssue> & { allowed?: readonly unknown[] },
  );
  toIssue(): ConfigurationIssue;
}

export const TRANSITION_IDS: readonly Transition[];
export const PIXEL_SWITCH_IDS: readonly PixelSwitch[];
export const PIXEL_SHAPE_IDS: readonly PixelShape[];

export function nearestName<T extends string>(
  value: unknown,
  candidates: readonly T[],
  options?: { maxDistance?: number },
): T | null;

export function validateKnownValue<T extends string>(
  value: unknown,
  allowed: readonly T[],
  options?: {
    aliases?: Readonly<Record<string, T>>;
    label?: string;
    path?: string;
  },
): T;

export function validateSpriteId(value: unknown): BuiltInSpriteId;
export function validateFieldId(value: unknown): FieldId;
export function validateTransition(value: unknown): Transition;
export function validatePixelShape(value: unknown): PixelShape;
export function validatePixelSwitch(value: unknown): PixelSwitch;
export function inspectEngineOptions(
  input: unknown,
  options?: InspectEngineOptionsSettings,
): InspectEngineOptionsResult;
export function validateEngineOptions<T extends Record<string, unknown>>(
  input: T,
  options?: ValidateEngineOptionsSettings,
): T & JoanEngineOptions;
export function validateRecipe(input: unknown): SpriteRecipe;
export function defineRecipe<T extends SpriteRecipe>(
  recipe: T,
): Readonly<T & SpriteRecipe>;
