import path from 'node:path';
import { findCodexBinary } from '../codex-adapter.js';
import { compareSemverLike, parseCodexVersionText } from '../codex-compat/codex-version-policy.js';
import { nowIso, runProcess, writeJsonAtomic } from '../fsx.js';
export async function detectCodex0139Capability(input = {}) {
    const fake = process.env.SKS_CODEX_0139_FAKE === '1';
    const codexBin = fake
        ? input.codexBin || process.env.CODEX_BIN || 'codex'
        : input.codexBin || process.env.CODEX_BIN || await findCodexBinary();
    const versionText = fake
        ? String(process.env.SKS_CODEX_VERSION_FAKE || 'codex-cli 0.139.0')
        : await readCodexVersionText(codexBin);
    const parsed = parseCodexVersionText(versionText);
    const atLeast139 = Boolean(parsed && compareSemverLike(parsed, '0.139.0') >= 0);
    const probeMode = process.env.SKS_CODEX_0139_PROBE === '1' ? 'feature-probe' : 'version-only';
    const probeTimeoutMs = Math.max(1, Number(process.env.SKS_CODEX_0139_PROBE_TIMEOUT_MS || 3000) || 3000);
    const featureProbeResults = probeMode === 'feature-probe'
        ? await probeCodex0139Features(codexBin, { fake, timeoutMs: probeTimeoutMs })
        : {
            marketplace_list_json: 'skipped',
            sandbox_profile_alias: 'skipped',
            interrupt_agent_event_mapping: 'skipped',
            rich_tool_schema_preservation: 'skipped',
            doctor_env_redaction: 'skipped',
            code_mode_web_search: 'skipped'
        };
    const marketplaceOk = atLeast139 && (probeMode === 'version-only' || featureProbeResults.marketplace_list_json !== 'failed');
    const profileAliasOk = atLeast139 && (probeMode === 'version-only' || featureProbeResults.sandbox_profile_alias !== 'failed');
    const interruptAgentOk = atLeast139 && (probeMode === 'version-only' || featureProbeResults.interrupt_agent_event_mapping !== 'failed');
    const richSchemaOk = atLeast139 && (probeMode === 'version-only' || featureProbeResults.rich_tool_schema_preservation !== 'failed');
    const doctorEnvOk = atLeast139 && (probeMode === 'version-only' || featureProbeResults.doctor_env_redaction !== 'failed');
    const codeSearchOk = atLeast139 && (probeMode === 'version-only' || featureProbeResults.code_mode_web_search !== 'failed');
    const probeErrorSummary = Object.entries(featureProbeResults)
        .filter(([, status]) => status === 'failed')
        .map(([name]) => `${name}:failed`);
    const blockers = [
        ...(!codexBin ? ['codex_cli_missing'] : []),
        ...(atLeast139 ? [] : ['codex_0_139_required_for_search_schema_marketplace_features']),
        ...(probeMode === 'feature-probe' && featureProbeResults.marketplace_list_json === 'failed' ? ['codex_marketplace_list_json_probe_failed'] : []),
        ...(probeMode === 'feature-probe' && featureProbeResults.sandbox_profile_alias === 'failed' ? ['codex_sandbox_profile_alias_probe_failed'] : []),
        ...(probeMode === 'feature-probe' && featureProbeResults.interrupt_agent_event_mapping === 'failed' ? ['codex_interrupt_agent_probe_failed'] : []),
        ...(probeMode === 'feature-probe' && featureProbeResults.rich_tool_schema_preservation === 'failed' ? ['codex_rich_tool_schema_probe_failed'] : []),
        ...(probeMode === 'feature-probe' && featureProbeResults.doctor_env_redaction === 'failed' ? ['codex_doctor_env_redaction_probe_failed'] : []),
        ...(probeMode === 'feature-probe' && featureProbeResults.code_mode_web_search === 'failed' ? ['codex_code_mode_web_search_probe_failed'] : [])
    ];
    return {
        schema: 'sks.codex-0139-capability.v1',
        ok: atLeast139 && blockers.length === 0,
        probe_mode: probeMode,
        probe_timeout_ms: probeTimeoutMs,
        probe_error_summary: probeErrorSummary,
        codex_bin: codexBin || null,
        version_text: versionText || null,
        parsed_version: parsed,
        supports_code_mode_web_search: codeSearchOk,
        supports_code_mode_web_search_real_verified: false,
        supports_rich_tool_schemas: richSchemaOk,
        supports_doctor_env_details: doctorEnvOk,
        supports_marketplace_source_field: marketplaceOk,
        supports_plugin_catalog_cache: atLeast139,
        supports_sandbox_profile_alias: profileAliasOk,
        supports_interrupt_agent_rename: interruptAgentOk,
        feature_probe_results: featureProbeResults,
        blockers
    };
}
export async function writeCodex0139CapabilityArtifacts(root, input = {}) {
    const capability = await detectCodex0139Capability({ codexBin: input.codexBin || null });
    const report = { ...capability, generated_at: nowIso() };
    const rootArtifact = path.join(root, '.sneakoscope', 'codex-0139-capability.json');
    await writeJsonAtomic(rootArtifact, report);
    let missionArtifact = null;
    if (input.missionId) {
        missionArtifact = path.join(root, '.sneakoscope', 'missions', input.missionId, 'codex-0139-capability.json');
        await writeJsonAtomic(missionArtifact, report);
    }
    return { report, root_artifact: rootArtifact, mission_artifact: missionArtifact };
}
async function readCodexVersionText(codexBin) {
    if (!codexBin)
        return null;
    const result = await runProcess(codexBin, ['--version'], { timeoutMs: 10_000, maxOutputBytes: 16 * 1024 }).catch((err) => ({
        code: 1,
        stdout: '',
        stderr: err?.message || String(err)
    }));
    const text = `${result.stdout || ''}${result.stderr || ''}`.trim();
    return result.code === 0 ? text : text || null;
}
async function probeCodex0139Features(codexBin, opts = {}) {
    if (opts.fake) {
        return {
            marketplace_list_json: process.env.SKS_CODEX_0139_FAKE_MARKETPLACE_FAIL === '1' ? 'failed' : 'passed',
            sandbox_profile_alias: process.env.SKS_CODEX_0139_FAKE_PROFILE_ALIAS_FAIL === '1' ? 'failed' : 'passed',
            interrupt_agent_event_mapping: process.env.SKS_CODEX_0139_FAKE_INTERRUPT_FAIL === '1' ? 'failed' : 'passed',
            rich_tool_schema_preservation: process.env.SKS_CODEX_0139_FAKE_RICH_SCHEMA_FAIL === '1' ? 'failed' : 'passed',
            doctor_env_redaction: process.env.SKS_CODEX_0139_FAKE_DOCTOR_ENV_FAIL === '1' ? 'failed' : 'passed',
            code_mode_web_search: process.env.SKS_CODEX_0139_FAKE_WEB_SEARCH_FAIL === '1' ? 'failed' : 'passed'
        };
    }
    const timeoutMs = Math.max(1, Number(opts.timeoutMs || process.env.SKS_CODEX_0139_PROBE_TIMEOUT_MS || 3000) || 3000);
    if (!codexBin) {
        return {
            marketplace_list_json: 'failed',
            sandbox_profile_alias: 'failed',
            interrupt_agent_event_mapping: 'skipped',
            rich_tool_schema_preservation: 'skipped',
            doctor_env_redaction: 'skipped',
            code_mode_web_search: 'skipped'
        };
    }
    const marketplace = await runProcess(codexBin, ['plugin', 'marketplace', 'list', '--json'], { timeoutMs, maxOutputBytes: 256 * 1024 }).catch(() => ({ code: 1, stdout: '' }));
    const marketplaceListJson = marketplace.code === 0 && marketplaceSourcesPresent(marketplace.stdout) ? 'passed' : 'failed';
    const help = await runProcess(codexBin, ['--help'], { timeoutMs, maxOutputBytes: 256 * 1024 }).catch(() => ({ code: 1, stdout: '' }));
    const sandboxHelp = await runProcess(codexBin, ['sandbox', '--help'], { timeoutMs, maxOutputBytes: 256 * 1024 }).catch(() => ({ code: 1, stdout: '' }));
    const aliasOk = help.code === 0 && codexHelpSupportsSandboxProfileAlias(help.stdout)
        || sandboxHelp.code === 0 && codexHelpSupportsSandboxProfileAlias(sandboxHelp.stdout);
    return {
        marketplace_list_json: marketplaceListJson,
        sandbox_profile_alias: aliasOk ? 'passed' : 'failed',
        interrupt_agent_event_mapping: 'skipped',
        rich_tool_schema_preservation: 'skipped',
        doctor_env_redaction: 'skipped',
        code_mode_web_search: 'skipped'
    };
}
export function marketplaceSourcesPresent(stdout) {
    try {
        const parsed = JSON.parse(String(stdout || ''));
        const rows = Array.isArray(parsed) ? parsed : Array.isArray(parsed?.marketplaces) ? parsed.marketplaces : Array.isArray(parsed?.items) ? parsed.items : [];
        if (!rows.length)
            return true;
        return rows.every((row) => typeof row?.source === 'string' && row.source.length > 0
            || typeof row?.marketplaceSource?.source === 'string' && row.marketplaceSource.source.length > 0
            || typeof row?.root === 'string' && row.root.length > 0);
    }
    catch {
        return false;
    }
}
export function codexHelpSupportsSandboxProfileAlias(stdout) {
    return /(^|\s)-P[,\s]+--(?:permissions-)?profile\b|--(?:permissions-)?profile[,\s]+-P\b|(^|\s)-P\b/m.test(String(stdout || ''));
}
export function redactCodexDoctorEnvDetails(value) {
    if (Array.isArray(value))
        return value.map((item) => redactCodexDoctorEnvDetails(item));
    if (!value || typeof value !== 'object') {
        return secretLikeValue(value) ? '<redacted>' : value;
    }
    return Object.fromEntries(Object.entries(value).map(([key, entry]) => {
        if (secretLikeKey(key) || secretLikeValue(entry))
            return [key, '<redacted>'];
        return [key, redactCodexDoctorEnvDetails(entry)];
    }));
}
function secretLikeKey(key) {
    return /(?:api[_-]?key|auth[_-]?token|secret|password|credential|bearer|session[_-]?token)/i.test(key);
}
function secretLikeValue(value) {
    const text = typeof value === 'string' ? value : '';
    return /(?:sk-[A-Za-z0-9_-]{6,}|Bearer\s+[A-Za-z0-9._-]{8,}|[A-Za-z0-9._-]{12,}\.[A-Za-z0-9._-]{12,}\.[A-Za-z0-9._-]{12,})/.test(text);
}
//# sourceMappingURL=codex-0139-capability.js.map