'use strict';

/**
 * Routing reason codes — Item B of provider-routing deep-dive.
 *
 * Frozen vocabulary for "why did this model/provider/harness get
 * selected for this call." Mirrors OpenClaw's `selection.ts:60-68`
 * reason codes (`pinned`, `forced_pi`, `forced_plugin`,
 * `forced_plugin_fallback_to_pi`, `auto_plugin`, `auto_pi_fallback`),
 * adapted to Wall-E's vocabulary (no PI vs plugin split — Wall-E has
 * one harness today; the distinction is provider/model selection
 * mechanism).
 *
 * Used by:
 *   - skill-harness-registry.js: returned in `supports().reason`
 *   - chat.js: emitted via recovery-logger on each model selection
 *   - skill-fallback.js: tags each candidate attempt
 *
 * Adding a new reason: bump the major plugin API version (Item A of
 * plugin-SDK deep-dive) — log analysis tooling will rely on this enum
 * being frozen across daemon versions.
 */

const ROUTING_REASONS = Object.freeze({
  /** User explicitly pinned the model for this call (opts.model passed). */
  PINNED: 'pinned',

  /** Cron-job-level model override applied (Item A of this deep-dive). */
  CRON_OVERRIDE: 'cron_override',

  /** Skill manifest's model_candidates supplied this model. */
  SKILL_MANIFEST: 'skill_manifest',

  /** A previous candidate failed; this is a fallback attempt. */
  FALLBACK: 'fallback',

  /** Provider-default model selected (no override anywhere). */
  AUTO_PROVIDER_DEFAULT: 'auto_provider_default',

  /** Tier-selector chose this model based on prompt complexity. */
  AUTO_TIER: 'auto_tier',

  /** Scorecard heuristic picked the model. */
  AUTO_SCORECARD: 'auto_scorecard',

  /** Forced via env var (WALLE_MODEL or WALLE_MODEL_FAST/BALANCED/QUALITY). */
  ENV_OVERRIDE: 'env_override',

  /** Db-backed default (brain_metadata key=walle_model). */
  DB_DEFAULT: 'db_default',
});

const ALL_REASONS = Object.freeze(Object.values(ROUTING_REASONS));

/** Returns true if `s` is a known routing reason code. */
function isValidReason(s) {
  return typeof s === 'string' && ALL_REASONS.includes(s);
}

/**
 * Compose a routing-decision log entry suitable for recovery-logger.
 * Pure helper — accepts the resolved `{model, provider, reason, ...}`
 * and returns a normalized payload.
 */
function buildRoutingDecision({ model, provider, reason, fallbackOf, durationMs, cost, attempt }) {
  return {
    model: model || null,
    provider: provider || null,
    reason: isValidReason(reason) ? reason : null,
    fallbackOf: fallbackOf || null,
    attempt: typeof attempt === 'number' ? attempt : null,
    durationMs: typeof durationMs === 'number' ? durationMs : null,
    cost: typeof cost === 'number' ? cost : null,
  };
}

module.exports = {
  ROUTING_REASONS,
  ALL_REASONS,
  isValidReason,
  buildRoutingDecision,
};
