import {
  SEAT_MODEL_ALIASES,
  SEAT_NATIVE_ALIASES,
  SEAT_UNSUPPORTED_BOUNDARY,
} from "./seat-constants.mjs";
import { validateForwardedArgv } from "./seat-env.mjs";

const GPT_MODEL_RE = /^gpt-[A-Za-z0-9][A-Za-z0-9._-]*$/;
const NATIVE_MODEL_RE = /^claude-/;

export function resolveSeatModelToken(token) {
  const raw = String(token || "").trim();
  if (!raw) return { ok: false, reason: "missing-model", message: "seat-remote: --model is required" };
  if (SEAT_NATIVE_ALIASES[raw] || NATIVE_MODEL_RE.test(raw) || raw in SEAT_NATIVE_ALIASES) {
    return { ok: false, reason: "unsupported-security-boundary", message: SEAT_UNSUPPORTED_BOUNDARY };
  }
  if (SEAT_MODEL_ALIASES[raw]) return { ok: true, model: SEAT_MODEL_ALIASES[raw], source: raw };
  if (GPT_MODEL_RE.test(raw)) return { ok: true, model: raw, source: raw };
  return { ok: false, reason: "unknown-model", message: `seat-remote: unknown seat model ${raw}` };
}

export function parseWrapperModel(argv) {
  let model = null;
  let duplicate = false;
  const forwarded = [];
  let index = 0;
  while (index < argv.length) {
    const arg = argv[index];
    if (arg === "--model") {
      if (index + 1 >= argv.length) return { ok: false, reason: "model-value-missing" };
      if (model !== null) duplicate = true;
      model = argv[index + 1];
      index += 2;
      continue;
    }
    if (arg.startsWith("--model=")) {
      if (model !== null) duplicate = true;
      model = arg.slice("--model=".length);
      index += 1;
      continue;
    }
    if (arg === "--fallback-model" || arg.startsWith("--fallback-model=")) {
      return { ok: false, reason: "fallback-model-forbidden" };
    }
    forwarded.push(arg);
    index += 1;
  }
  if (duplicate) return { ok: false, reason: "duplicate-wrapper-model" };
  if (!model) return { ok: false, reason: "missing-model" };
  const resolved = resolveSeatModelToken(model);
  if (!resolved.ok) return resolved;
  return { ok: true, model: resolved.model, argv: forwarded };
}

export function stripForwardedModelOverrides(argv) {
  const check = validateForwardedArgv(argv);
  if (!check.ok) {
    const reason = check.errors[0]?.startsWith("deny:") ? "forwarded-security-arg" : check.errors[0] || "forwarded-invalid";
    return { ok: false, reason };
  }
  return { ok: true, argv: [...argv] };
}

export function validateInheritedModelEnv(env, boundModel) {
  const violations = [];
  for (const [key, value] of Object.entries(env || {})) {
    if (!key.startsWith("ANTHROPIC_") && !key.startsWith("CCP_") && key !== "CLAUDE_CODE_SUBAGENT_MODEL") continue;
    if (value === undefined || value === "") continue;
    if (key === "ANTHROPIC_BASE_URL" || key === "ANTHROPIC_AUTH_TOKEN") {
      violations.push(key);
      continue;
    }
    if (key === "ANTHROPIC_SMALL_FAST_MODEL" || key.startsWith("ANTHROPIC_DEFAULT_") || key === "CLAUDE_CODE_SUBAGENT_MODEL") {
      if (value !== boundModel) violations.push(key);
      continue;
    }
    if (key === "ANTHROPIC_MODEL") violations.push(key);
    if (key.startsWith("CCP_")) violations.push(key);
  }
  if (env?.CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY && env.CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY !== "0") {
    violations.push("CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY");
  }
  return violations;
}

export function stripSeatModelEnv(env, boundModel) {
  const next = { ...env };
  for (const key of Object.keys(next)) {
    if (key === "ANTHROPIC_SMALL_FAST_MODEL" || key.startsWith("ANTHROPIC_DEFAULT_") || key === "CLAUDE_CODE_SUBAGENT_MODEL") {
      if (next[key] !== boundModel) delete next[key];
      continue;
    }
    if (
      key === "ANTHROPIC_MODEL"
      || key.startsWith("CCP_")
      || key === "ANTHROPIC_API_KEY"
      || key === "ANTHROPIC_AUTH_TOKEN"
      || key === "ANTHROPIC_BASE_URL"
      || key === "OPENAI_API_KEY"
      || key === "CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY"
    ) {
      delete next[key];
    }
  }
  return next;
}

export function buildSeatRuntimeEnv(profileEnv, boundModel, proxyBaseUrl) {
  const next = stripSeatModelEnv(profileEnv, boundModel);
  if (!proxyBaseUrl) throw new Error("seat-runtime-env: proxy base url required");
  next.ANTHROPIC_BASE_URL = proxyBaseUrl;
  for (const key of ["ANTHROPIC_AUTH_TOKEN", "ANTHROPIC_API_KEY", "OPENAI_API_KEY"]) {
    delete next[key];
  }
  return next;
}
