// OmniRoute integration — routes the Codex and Free Claude Code agents through
// the local OmniRoute gateway (http://localhost:20128) so they build for FREE
// across 90+ free providers, instead of a paid API or the (uninstalled)
// fcc-server. OmniRoute speaks BOTH protocols the CLIs need:
//   • /v1/messages  (Anthropic)  ← the `claude` CLI  (Free Claude Code)
//   • /v1/responses (OpenAI)     ← the `codex` CLI
//
// All verified live: big-pickle drives both. The catch with the free reasoning
// models is they loop unless told to answer immediately — hence OMNIROUTE_STEER.

export const OMNIROUTE_BASE = process.env.OMNIROUTE_BASE_URL || "http://localhost:20128";
// Proven-reliable free coding model on this gateway (deepseek-v4-flash loops).
export const OMNIROUTE_FREE_MODEL = process.env.OMNIROUTE_MODEL || "oc/big-pickle";
// Dummy key — the free providers are keyless, but the CLIs require *something*.
export const OMNIROUTE_KEY = process.env.OMNIROUTE_API_KEY || "free-local";

// Without this, the free reasoning models deliberate until they exhaust the
// token budget and never act. This cuts reasoning from ~4000 tokens to ~100 and
// makes them actually write files / run tools.
export const OMNIROUTE_STEER =
  "Answer immediately and act. Do NOT overthink or deliberate at length. When the task needs a file written or a command run, use your tools right away, then stop. Keep reasoning to an absolute minimum.";

const MODEL_RE = /^[A-Za-z0-9._:/-]+$/;
function safeModel(model?: string | null): string {
  return model && MODEL_RE.test(model) ? model : OMNIROUTE_FREE_MODEL;
}

// `codex exec` provider flags — defines an "omniroute" provider inline (no need
// to touch ~/.codex/config.toml, so your own Codex setup is untouched).
// wire_api MUST be "responses": codex-cli ≥0.142 dropped chat-completions.
export function omnirouteCodexArgs(model?: string | null): string[] {
  return [
    "-c", "model_provider=omniroute",
    "-c", "model_providers.omniroute.name=OmniRoute",
    "-c", `model_providers.omniroute.base_url=${OMNIROUTE_BASE}/v1`,
    "-c", "model_providers.omniroute.wire_api=responses",
    "-c", "model_providers.omniroute.env_key=OMNIROUTE_API_KEY",
    "--model", safeModel(model),
  ];
}
export function omnirouteCodexEnv(): Record<string, string> {
  return { OMNIROUTE_API_KEY: OMNIROUTE_KEY };
}

// Env that points the `claude` CLI at OmniRoute's Anthropic endpoint. Setting
// ANTHROPIC_API_KEY is what makes the CLI use the gateway instead of the OAuth
// creds saved by `claude login`.
export function omnirouteClaudeEnv(model?: string | null): Record<string, string> {
  const m = safeModel(model);
  return {
    ANTHROPIC_BASE_URL: OMNIROUTE_BASE,
    ANTHROPIC_API_KEY: OMNIROUTE_KEY,
    ANTHROPIC_AUTH_TOKEN: OMNIROUTE_KEY,
    ANTHROPIC_MODEL: m,
    ANTHROPIC_SMALL_FAST_MODEL: m,
    CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY: "1",
  };
}

// Prepend the steer to a prompt (used for both CLIs).
export function withSteer(prompt: string): string {
  return `${OMNIROUTE_STEER}\n\n${prompt}`;
}

// Is the gateway up? Probes the OpenAI model list (cheap, keyless).
export async function probeOmniRoute(): Promise<boolean> {
  try {
    const ctl = new AbortController();
    const t = setTimeout(() => ctl.abort(), 1500);
    const r = await fetch(`${OMNIROUTE_BASE}/v1/models`, { signal: ctl.signal });
    clearTimeout(t);
    return r.ok;
  } catch {
    return false;
  }
}
