import { buildAuthCenterReport } from "../../../auth.js";
import { KNOWN_PROVIDER_IDS, listUserModelAliases, normalizeProviderId, parseProviderModelArg, readProviderRegistry, resolveUserModelAlias, } from "../../../../providers/model-registry.js";
import { groupProviderModelsByProvider, renderProviderModelTable } from "../../../../providers/model-table.js";
import { formatThinkingModelVariant, nextThinkingLevel, normalizeThinkingLevel, normalizeThinkingVariant, thinkingLevelsFor } from "../../../../providers/thinking-levels.js";
import { resolveRuntimeBootstrap } from "../../../../runtime/runtime-bootstrap.js";
import { style } from "../../../../util/theme.js";
import { errorSlashResult, okSlashResult } from "../result.js";
export function buildRoutingSlashCommands() {
    return [
        {
            name: "/auth",
            aliases: ["/login"],
            group: "routing",
            summary: "Show provider auth status",
            usage: "/auth [provider] [--setup] [--doctor]",
            examples: ["/auth", "/auth codex --doctor"],
            handler: async (ctx, args) => {
                const target = args.positional.find((token) => !token.startsWith("-"));
                const report = await buildAuthCenterReport(target, { env: ctx.env });
                if (args.flags.json)
                    return okSlashResult({ json: report });
                return okSlashResult({
                    text: renderAuthReport(report, Boolean(args.flags.setup || args.flags.doctor)),
                });
            },
        },
        {
            name: "/providers",
            aliases: [":providers"],
            group: "routing",
            summary: "List providers",
            usage: "/providers",
            examples: ["/providers"],
            handler: async (ctx) => {
                const providers = await readProviderRegistry({ env: ctx.env });
                return okSlashResult({ text: renderProviderModelTable(providers, { currentProvider: ctx.state.provider, currentModel: ctx.state.model, currentThinking: ctx.state.thinking, compactAliases: true, activeProviderTab: ctx.state.activeProviderTab }) });
            },
        },
        {
            name: "/provider",
            aliases: ["/p"],
            group: "routing",
            summary: "Switch provider for this session",
            usage: "/provider <name>",
            examples: ["/provider codex"],
            handler: async (ctx, args) => {
                const provider = String(args.positional[0] ?? "")
                    .trim()
                    .toLowerCase();
                const valid = ["auto", ...KNOWN_PROVIDER_IDS];
                const normalized = normalizeProviderId(provider);
                if (!provider || !valid.includes(normalized)) {
                    return okSlashResult({
                        text: `${style.phosphorDim(`\n  Available: ${valid.join(", ")}`)}\n${style.phosphorDim("  Usage: /provider codex\n")}`,
                    });
                }
                return applyProviderOverride(ctx, normalized);
            },
        },
        {
            name: "/models",
            aliases: [":models"],
            group: "routing",
            summary: "List model aliases",
            usage: "/models",
            examples: ["/models"],
            handler: async (ctx) => {
                const aliases = await listUserModelAliases({ env: ctx.env });
                const lines = [style.phosphorBold("\n  User Model Aliases:")];
                const entries = Object.entries(aliases);
                if (entries.length === 0)
                    lines.push(style.phosphorDim("    (none)"));
                for (const [alias, target] of entries)
                    lines.push(style.phosphorDim(`    ${alias} -> ${target}`));
                lines.push(style.phosphorDim("  Use `omk model alias add fast deepseek/flash` to persist aliases.\n"));
                return okSlashResult({ text: lines.join("\n") });
            },
        },
        {
            name: "/model",
            aliases: ["/m"],
            group: "routing",
            summary: "Show or set model [+thinking variant] for this session",
            usage: "/model [provider/model|model[:level]]",
            examples: ["/model", "/model codex/codex-cli", "/model deepseek/pro:max", "/model kimi/k2.6:high", "/model deepseek-v4-pro:max", "/think variant code-high"],
            handler: async (ctx, args) => {
                const raw = args.positional.join(" ").trim();
                if (!raw) {
                    const providers = await readProviderRegistry({ env: ctx.env });
                    const providerGroups = groupProviderModelsByProvider(providers);
                    if (args.flags.json) {
                        return okSlashResult({
                            json: {
                                schema: "omk.slash.model-groups.v1",
                                currentProvider: ctx.state.provider,
                                currentModel: ctx.state.model,
                                currentThinking: ctx.state.thinking,
                                providerGroups,
                            },
                        });
                    }
                    return okSlashResult({
                        text: renderProviderModelTable(providers, {
                            currentProvider: ctx.state.provider,
                            currentModel: ctx.state.model,
                            currentThinking: ctx.state.thinking,
                            activeProviderTab: ctx.state.activeProviderTab,
                        }),
                    });
                }
                // Parse model + optional :thinkingLevel
                const parsed = parseProviderModelArg(raw);
                const ref = modelRefFromParsed(parsed, raw);
                const thinking = parsed.thinkingLevel
                    ? await validateThinkingOverride(ctx, ref, parsed.thinkingLevel)
                    : undefined;
                if (thinking && !thinking.ok)
                    return thinking.result;
                const result = await applyModelOverride(ctx, ref);
                return thinking?.ok
                    ? applyThinkingOverride(ctx, result, thinking.level, thinking.levels)
                    : result;
            },
        },
        {
            name: "/think",
            aliases: ["/thinking", ":think"],
            group: "routing",
            summary: "Show, cycle, or set model thinking variant",
            usage: "/think [next|medium|high|xhigh|max|variant <name>]",
            examples: ["/think", "/think next", "/think high", "/think variant code-high", "/think varint review-xhigh"],
            handler: async (ctx, args) => {
                const requested = args.positional[0]?.trim().toLowerCase();
                const levels = thinkingLevelsFor(ctx.state.provider, ctx.state.model);
                const wantsCustomVariant = requested === "variant" || requested === "varint" || requested === "v";
                const customVariant = wantsCustomVariant ? normalizeThinkingVariant(args.positional[1]) : undefined;
                if (wantsCustomVariant) {
                    if (!customVariant) {
                        return okSlashResult({
                            text: style.phosphorDim(`\n  Usage: /think variant <name>\n  Example: /think variant code-high\n  Alias: /think varint <name>\n  Allowed: letters, numbers, dot, underscore, colon, hyphen.\n`),
                        });
                    }
                    ctx.env.OMK_THINKING = customVariant;
                    ctx.env.OMK_MODEL_VARIANT = formatThinkingModelVariant(ctx.state.model, customVariant);
                    return okSlashResult({
                        statePatch: { thinking: customVariant, updatedAt: new Date().toISOString() },
                        text: [
                            style.phosphor(`\n  Thinking variant: ${customVariant}`),
                            style.phosphorDim("  Mode: custom variant"),
                            style.phosphorDim(`  Active: ${ctx.env.OMK_MODEL_VARIANT}`),
                            style.phosphorDim(`  Level cycle still available: ${levels.join(" → ")}\n`),
                        ].join("\n"),
                    });
                }
                const level = !requested || requested === "next" || requested === "tab"
                    ? nextThinkingLevel(ctx.state.thinking ?? ctx.env.OMK_THINKING, ctx.state.provider, ctx.state.model)
                    : normalizeThinkingLevel(requested);
                if (!level || !levels.includes(level)) {
                    return okSlashResult({
                        text: style.phosphorDim(`\n  Supported thinking levels for ${ctx.state.provider}/${ctx.state.model ?? "auto"}: ${levels.join(" → ")}\n  Usage: /think next | ${levels.join(" | ")} | variant <name>\n  Shortcut: /model ${ctx.state.provider ?? "kimi"}/${ctx.state.model ?? "auto"}:${levels[0]}\n`),
                    });
                }
                ctx.env.OMK_THINKING = level;
                ctx.env.OMK_MODEL_VARIANT = formatThinkingModelVariant(ctx.state.model, level);
                return okSlashResult({
                    statePatch: { thinking: level, updatedAt: new Date().toISOString() },
                    text: [
                        style.phosphor(`\n  Thinking variant: ${level}`),
                        style.phosphorDim(`  Cycle: ${levels.join(" → ")}`),
                        style.phosphorDim(`  Active: ${ctx.env.OMK_MODEL_VARIANT}`),
                        style.phosphorDim(`  Shortcut: /model ${ctx.state.provider ?? "kimi"}/${ctx.state.model ?? "auto"}:${level}`),
                        style.phosphorDim("  Custom variant: /think variant code-high  (alias: /think varint code-high)\n"),
                    ].join("\n"),
                });
            },
        },
        {
            name: "/use",
            aliases: [":use"],
            group: "routing",
            summary: "Switch provider/model [+thinking] by alias",
            usage: "/use <ref>[:level]",
            examples: ["/use codex/codex-cli", "/use fast", "/use deepseek/pro:max"],
            handler: async (ctx, args) => {
                const raw = args.positional.join(" ").trim();
                if (!raw)
                    return okSlashResult({
                        text: style.phosphorDim("\n  Usage: /use codex/codex-cli or /use fast or /use deepseek/pro:max\n"),
                    });
                const parsed = parseProviderModelArg(raw);
                const ref = modelRefFromParsed(parsed, raw);
                const thinking = parsed.thinkingLevel
                    ? await validateThinkingOverride(ctx, ref, parsed.thinkingLevel)
                    : undefined;
                if (thinking && !thinking.ok)
                    return thinking.result;
                const result = await applyModelOverride(ctx, ref);
                return thinking?.ok
                    ? applyThinkingOverride(ctx, result, thinking.level, thinking.levels)
                    : result;
            },
        },
    ];
}
function modelRefFromParsed(parsed, raw) {
    return `${parsed.provider ? `${parsed.provider}/` : ""}${parsed.model ?? raw}`;
}
async function validateThinkingOverride(ctx, ref, requestedThinking) {
    const level = normalizeThinkingLevel(requestedThinking);
    const resolved = await resolveUserModelAlias(ref, { env: ctx.env });
    const nextProvider = resolved.provider ?? ctx.state.provider;
    const nextModel = resolved.model ?? ctx.state.model;
    const levels = thinkingLevelsFor(nextProvider, nextModel);
    if (!level || !levels.includes(level)) {
        return {
            ok: false,
            result: errorSlashResult([
                style.metricsRed(`\n  Unsupported thinking level: ${requestedThinking}`),
                style.phosphorDim(`  Target: ${nextProvider ?? "auto"}/${nextModel ?? "auto"}`),
                style.phosphorDim(`  Supported: ${levels.join(" → ")}`),
                style.phosphorDim(`  Usage: /model ${ref}:${levels.join("|")}\n`),
            ].join("\n")),
        };
    }
    return { ok: true, level, levels };
}
function applyThinkingOverride(ctx, result, level, levels) {
    const nextModel = result.statePatch?.model ?? ctx.state.model;
    if (!nextModel)
        return result;
    ctx.env.OMK_THINKING = level;
    ctx.env.OMK_MODEL_VARIANT = formatThinkingModelVariant(nextModel, level);
    const statePatch = result.statePatch ?? {};
    result.statePatch = {
        ...statePatch,
        thinking: level,
        updatedAt: new Date().toISOString(),
    };
    result.text = [
        result.text?.trimEnd(),
        style.phosphorDim(`  Thinking: ${level}  (cycle: ${levels.join(" → ")})`),
    ].filter(Boolean).join("\n");
    return result;
}
async function applyProviderOverride(ctx, provider, model) {
    const bootstrap = await resolveRuntimeBootstrap({
        provider,
        model: model ?? ctx.state.model,
        cwd: ctx.input.root,
        env: ctx.env,
    });
    if (!bootstrap.ok) {
        const lines = [style.metricsRed(`\n  Provider not ready: ${provider}`)];
        if (bootstrap.reason)
            lines.push(style.phosphorDim(`  ${bootstrap.reason}`));
        for (const hint of bootstrap.setupHints.slice(0, 3))
            lines.push(style.phosphorDim(`  - ${hint}`));
        lines.push(style.phosphorDim(`  Restart/setup: omk auth ${provider} --setup\n`));
        return okSlashResult({ text: lines.join("\n") });
    }
    const statePatch = {
        bootstrap,
        provider: bootstrap.provider,
        model: bootstrap.selectedModel,
        updatedAt: new Date().toISOString(),
    };
    if (bootstrap.selectedModel)
        ctx.env.OMK_PROVIDER_MODEL = bootstrap.selectedModel;
    else
        delete ctx.env.OMK_PROVIDER_MODEL;
    return okSlashResult({
        statePatch,
        text: [
            style.phosphor(`\n  Provider switched for this session: ${bootstrap.provider}`),
            style.phosphorDim(`  Runtime: ${bootstrap.selectedRuntimeId ?? "auto"} | Model: ${bootstrap.selectedModel ?? "auto"}`),
            style.phosphorDim("  Persistent default unchanged; use `omk provider use` to persist.\n"),
        ].join("\n"),
    });
}
async function applyModelOverride(ctx, ref) {
    const resolved = await resolveUserModelAlias(ref, { env: ctx.env });
    const updatedAt = new Date().toISOString();
    const lines = [
        style.phosphor(`\n  Model override for this session: ${ref} → ${resolved.model}`),
    ];
    if (resolved.provider)
        lines.push(style.phosphorDim(`  Provider: ${resolved.provider}`));
    lines.push(style.phosphorDim("  Persistent default unchanged; use `omk model use` to persist.\n"));
    if (resolved.provider && resolved.provider !== ctx.state.provider) {
        const providerResult = await applyProviderOverride(ctx, resolved.provider, resolved.model);
        if (providerResult.statePatch?.provider !== resolved.provider)
            return providerResult;
        const providerPatch = providerResult.statePatch ?? {};
        const bootstrap = {
            ...(providerPatch.bootstrap ?? ctx.state.bootstrap),
            selectedModel: resolved.model,
        };
        ctx.env.OMK_PROVIDER_MODEL = resolved.model;
        return okSlashResult({
            statePatch: {
                ...providerPatch,
                bootstrap,
                model: resolved.model,
                updatedAt,
            },
            text: [providerResult.text?.trimEnd(), ...lines]
                .filter(Boolean)
                .join("\n"),
        });
    }
    const statePatch = {
        bootstrap: {
            ...ctx.state.bootstrap,
            selectedModel: resolved.model,
        },
        model: resolved.model,
        updatedAt,
    };
    ctx.env.OMK_PROVIDER_MODEL = resolved.model;
    return okSlashResult({ statePatch, text: lines.join("\n") });
}
function renderAuthReport(report, verbose) {
    const lines = [
        style.phosphorBold("OMK Auth Center"),
        style.phosphorDim(`Default provider: ${report.defaultProvider}`),
        style.phosphorDim(`Authority: ${report.authorityProvider}`),
    ];
    if (report.model)
        lines.push(style.phosphorDim(`Model: ${report.model}`));
    lines.push("");
    for (const provider of report.providers) {
        const mark = provider.available
            ? style.phosphorBold("✓")
            : provider.enabled
                ? style.phosphorDim("○")
                : style.phosphorDim("×");
        const state = provider.available
            ? "runtime ready"
            : provider.enabled
                ? "needs setup"
                : "disabled";
        const auth = provider.apiKeyEnv
            ? `${provider.authMethod} ${provider.apiKeyEnv}`
            : provider.authMethod;
        lines.push(`  ${mark} ${style.phosphor(provider.provider.padEnd(12))} ${style.phosphorDim(state.padEnd(14))} ${style.phosphorDim(auth)}`);
        if (verbose && provider.nextActions.length > 0) {
            for (const action of provider.nextActions.slice(0, 3))
                lines.push(style.phosphorDim(`      - ${action}`));
        }
    }
    lines.push("");
    lines.push(style.phosphorDim("Secret policy: tokenFilesRead=false, secretValuesPrinted=false"));
    lines.push(style.phosphorDim("Use `omk auth <provider> --setup` for setup actions."));
    return lines.join("\n");
}
