import { VALID_CLAUDE_DISPATCH_CEILINGS, VALID_CODEX_DISPATCH_CEILINGS, } from '../../config/oat-config.js';
import { buildCodexMaterializedTargetRoleName } from '../codex/codec/shared.js';
const DIRECT_DISPATCH_ROLE_PATTERN = /^oat-(?:phase-implementer|reviewer)(?:-|$)/;
export function isDirectDispatchRoleName(value) {
    return DIRECT_DISPATCH_ROLE_PATTERN.test(value.trim());
}
/** Codex materialized-role base names (must match sync-extension output). */
const CODEX_IMPLEMENTER_ROLE = 'oat-phase-implementer';
const CODEX_REVIEWER_ROLE = 'oat-reviewer';
/** Claude tier order, low → high, for above-orchestrator comparison. */
export const CLAUDE_TIER_ORDER = [
    'haiku',
    'sonnet',
    'opus',
    'fable',
];
const codexAdapter = {
    provider: 'codex',
    supportsCeiling: true,
    validValues: [...VALID_CODEX_DISPATCH_CEILINGS],
    mechanism: 'pinned-variant',
    compileToDispatchArgs(value, role, ctx) {
        if (!VALID_CODEX_DISPATCH_CEILINGS.includes(value)) {
            return null;
        }
        const target = ctx.target;
        if (!target?.model ||
            !target.effort ||
            isDirectDispatchRoleName(target.model)) {
            return null;
        }
        const baseRole = role === 'reviewer' ? CODEX_REVIEWER_ROLE : CODEX_IMPLEMENTER_ROLE;
        return {
            variant: buildCodexMaterializedTargetRoleName({
                agentName: baseRole,
                model: target.model,
                effort: target.effort,
            }),
        };
    },
    // Codex enforces via materialized model+effort roles, not model tier; there
    // is no above-orchestrator upgrade path to verify.
    verifyOnDispatch() {
        return false;
    },
};
function isAboveOrchestrator(value, orchestratorTier) {
    if (!orchestratorTier) {
        return false;
    }
    const requestedIndex = CLAUDE_TIER_ORDER.indexOf(value);
    const orchestratorIndex = CLAUDE_TIER_ORDER.indexOf(orchestratorTier);
    if (requestedIndex < 0 || orchestratorIndex < 0) {
        return false;
    }
    return requestedIndex > orchestratorIndex;
}
const claudeAdapter = {
    provider: 'claude',
    supportsCeiling: true,
    validValues: [...VALID_CLAUDE_DISPATCH_CEILINGS],
    mechanism: 'model-arg',
    compileToDispatchArgs(value) {
        if (isDirectDispatchRoleName(value) ||
            !VALID_CLAUDE_DISPATCH_CEILINGS.includes(value)) {
            return null;
        }
        return { model: value };
    },
    // Verify only when the request is above the orchestrator tier (upgrade path).
    verifyOnDispatch(value, ctx) {
        return isAboveOrchestrator(value, ctx.orchestratorTier);
    },
};
const cursorAdapter = {
    provider: 'cursor',
    supportsCeiling: true,
    validValues: [],
    mechanism: 'model-arg',
    compileToDispatchArgs(value) {
        const model = value.trim();
        return model && !isDirectDispatchRoleName(model) ? { model } : null;
    },
    // Cursor model slugs do not share a total order, so upgrade verification is
    // not meaningful here; availability is checked by the identity oracle layer.
    verifyOnDispatch() {
        return false;
    },
};
function advisoryAdapter(provider) {
    return {
        provider,
        supportsCeiling: false,
        validValues: [],
        mechanism: 'none',
        compileToDispatchArgs() {
            return null;
        },
        verifyOnDispatch() {
            return false;
        },
    };
}
const REGISTERED_ADAPTERS = {
    codex: codexAdapter,
    claude: claudeAdapter,
    cursor: cursorAdapter,
};
/**
 * Look up the ceiling adapter for a provider. Unknown providers fall back to an
 * advisory no-op adapter (`supportsCeiling: false`, `mechanism: 'none'`,
 * `compileToDispatchArgs → null`).
 */
export function getCeilingAdapter(provider) {
    return REGISTERED_ADAPTERS[provider] ?? advisoryAdapter(provider);
}
