"use strict";
/**
 * Profile and target resolution — Phase C extraction from src/ccs.ts.
 *
 * Extracted from main() lines ~136–313 (after Phase B pre-dispatch).
 * Responsible for: dynamic imports of auth modules, profile detection, target type
 * resolution, Claude CLI detection, target adapter resolution, compatibility preflight
 * checks (preserved with duplication per plan risk note 5), binary detection, and
 * per-target argument normalization (droid routing + reasoning flag stripping,
 * codex reasoning normalization, native Claude effort normalization).
 *
 * Outputs a ResolvedProfile context object consumed by Phase D (environment-builder
 * argument normalization) and Phase E (per-profile dispatch flows).
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveProfileAndTarget = void 0;
const claude_detector_1 = require("../utils/claude-detector");
const config_manager_1 = require("../utils/config-manager");
const config_loader_facade_1 = require("../config/config-loader-facade");
const helpers_1 = require("../utils/helpers");
const ui_1 = require("../utils/ui");
const error_manager_1 = require("../utils/error-manager");
const config_loader_facade_2 = require("../config/config-loader-facade");
const browser_1 = require("../utils/browser");
const targets_1 = require("../targets");
const target_resolver_1 = require("../targets/target-resolver");
const droid_reasoning_runtime_1 = require("../targets/droid-reasoning-runtime");
const droid_command_router_1 = require("../targets/droid-command-router");
const cliproxy_profile_bridge_1 = require("../api/services/cliproxy-profile-bridge");
const environment_builder_1 = require("./environment-builder");
const cli_argument_parser_1 = require("./cli-argument-parser");
function usesImplicitDefaultProfile(cleanArgs) {
    return cleanArgs.length === 0 || cleanArgs[0]?.startsWith('-') === true;
}
function buildNativeCodexDefaultProfile() {
    return {
        type: 'default',
        name: 'default',
        message: 'Using native Codex auth; CCS default profile is not applied to Codex target.',
    };
}
// ========== Profile and Target Resolver ==========
/**
 * Resolve profile detection, target type, adapter, binary, and per-target arg normalization.
 *
 * Throws ProfileError (caught by main() try/catch) for unknown profiles.
 * Calls process.exit(1) for hard-stop conditions (adapter not found, binary not found, etc.).
 *
 * NOTE: The compatibility preflight block for non-settings profiles (else branch) is
 * INTENTIONALLY duplicated between here (Phase C) and the settings flow (Phase E).
 * Per plan risk note 5, do NOT dedupe in this PR.
 */
async function resolveProfileAndTarget(ctx) {
    const { args, browserLaunchOverride } = ctx;
    // Dynamic imports — preserved at original call sites for latency/circular-dep avoidance.
    // InstanceManager, ProfileRegistry, AccountContext, ProfileContinuity are loaded here
    // to match original ordering; their resolved values flow into Phase E via the detector
    // instance or are re-imported inside flow handlers.
    const ProfileDetectorModule = await Promise.resolve().then(() => __importStar(require('../auth/profile-detector')));
    const ProfileDetectorClass = ProfileDetectorModule.default;
    await Promise.resolve().then(() => __importStar(require('../management/instance-manager')));
    await Promise.resolve().then(() => __importStar(require('../auth/profile-registry')));
    await Promise.resolve().then(() => __importStar(require('../auth/account-context')));
    await Promise.resolve().then(() => __importStar(require('../auth/profile-continuity-inheritance')));
    const detector = new ProfileDetectorClass();
    // Detect profile (strip --target flags before profile detection)
    const cleanArgs = (0, target_resolver_1.stripTargetFlag)(args);
    const { profile, remainingArgs } = (0, cli_argument_parser_1.detectProfile)(cleanArgs);
    let profileInfo = detector.detectProfileType(profile);
    let resolvedTarget;
    try {
        resolvedTarget = (0, target_resolver_1.resolveTargetType)(args, profileInfo.target ? { target: profileInfo.target } : undefined);
    }
    catch (error) {
        console.error((0, ui_1.fail)(error.message));
        process.exit(1);
        // Unreachable; needed so TS knows resolvedTarget is always assigned below
        throw error;
    }
    if (resolvedTarget === 'codex' && usesImplicitDefaultProfile(cleanArgs)) {
        profileInfo = buildNativeCodexDefaultProfile();
    }
    // Detect Claude CLI (needed for claude target and all CLIProxy-derived flows)
    const claudeCliRaw = (0, claude_detector_1.detectClaudeCli)();
    if (resolvedTarget === 'claude' && !claudeCliRaw) {
        await error_manager_1.ErrorManager.showClaudeNotFound();
        process.exit(1);
    }
    const claudeCli = claudeCliRaw || '';
    // Resolve non-claude target adapter once.
    const targetAdapter = resolvedTarget !== 'claude' ? ((0, targets_1.getTarget)(resolvedTarget) ?? null) : null;
    let resolvedSettingsPath;
    let resolvedSettings;
    let resolvedCliproxyBridge;
    // Preflight unsupported profile/target combinations BEFORE binary detection,
    // so users get the most actionable error even when the target CLI is not installed.
    if (resolvedTarget !== 'claude') {
        if (!targetAdapter) {
            console.error((0, ui_1.fail)(`Target adapter not found for "${resolvedTarget}"`));
            process.exit(1);
        }
        if (profileInfo.type === 'settings') {
            resolvedSettingsPath = profileInfo.settingsPath
                ? (0, helpers_1.expandPath)(profileInfo.settingsPath)
                : (0, config_manager_1.getSettingsPath)(profileInfo.name);
            resolvedSettings = (0, config_loader_facade_1.loadSettings)(resolvedSettingsPath);
            resolvedCliproxyBridge = (0, cliproxy_profile_bridge_1.resolveCliproxyBridgeMetadata)(resolvedSettings);
            const compatibility = (0, targets_1.evaluateTargetRuntimeCompatibility)({
                target: resolvedTarget,
                profileType: profileInfo.type,
                cliproxyBridgeProvider: resolvedCliproxyBridge?.provider ?? null,
            });
            if (!compatibility.supported) {
                console.error((0, ui_1.fail)(compatibility.reason || `${targetAdapter.displayName} does not support this profile.`));
                if (compatibility.suggestion) {
                    console.error((0, ui_1.info)(compatibility.suggestion));
                }
                process.exit(1);
            }
        }
        else {
            // NOTE: Intentional duplication — Phase E settings flow re-runs this check post-load.
            // Per plan risk note 5, preserve verbatim; do NOT dedupe.
            const compatibility = (0, targets_1.evaluateTargetRuntimeCompatibility)({
                target: resolvedTarget,
                profileType: profileInfo.type,
                cliproxyProvider: profileInfo.type === 'cliproxy' ? profileInfo.provider : undefined,
                isComposite: profileInfo.type === 'cliproxy' ? Boolean(profileInfo.isComposite) : undefined,
            });
            if (!compatibility.supported) {
                console.error((0, ui_1.fail)(compatibility.reason || `${targetAdapter.displayName} does not support this profile.`));
                if (compatibility.suggestion) {
                    console.error((0, ui_1.info)(compatibility.suggestion));
                }
                process.exit(1);
            }
        }
        if (profileInfo.type === 'default') {
            if (!targetAdapter.supportsProfileType('default')) {
                console.error((0, ui_1.fail)(`${targetAdapter.displayName} does not support default profile mode`));
                process.exit(1);
            }
            // For default mode, Droid requires explicit credentials from environment.
            if (resolvedTarget === 'droid') {
                const baseUrl = process.env['ANTHROPIC_BASE_URL'] || '';
                const apiKey = process.env['ANTHROPIC_AUTH_TOKEN'] || '';
                if (!baseUrl.trim() || !apiKey.trim()) {
                    console.error((0, ui_1.fail)(`${targetAdapter.displayName} default mode requires ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN`));
                    console.error((0, ui_1.info)('Use a settings-based profile instead: ccs glm --target droid'));
                    process.exit(1);
                }
            }
        }
    }
    // For non-claude targets, verify target binary exists once and pass it through.
    const targetBinaryInfo = targetAdapter?.detectBinary() ?? null;
    const browserConfig = (0, config_loader_facade_2.getBrowserConfig)();
    const claudeAttachConfig = resolvedTarget === 'claude' ? (0, browser_1.getEffectiveClaudeBrowserAttachConfig)(browserConfig) : undefined;
    const codexRuntimeConfigOverrides = (0, environment_builder_1.resolveCodexRuntimeConfigOverrides)(resolvedTarget, browserLaunchOverride);
    const claudeBrowserExposure = resolvedTarget === 'claude'
        ? (0, browser_1.resolveBrowserExposure)({
            enabled: claudeAttachConfig?.enabled ?? browserConfig.claude.enabled,
            policy: browserConfig.claude.policy,
        }, browserLaunchOverride)
        : undefined;
    const codexBrowserExposure = resolvedTarget === 'codex'
        ? (0, browser_1.resolveBrowserExposure)(browserConfig.codex, browserLaunchOverride)
        : undefined;
    const blockedBrowserOverrideWarning = resolvedTarget === 'claude' && claudeBrowserExposure
        ? (0, browser_1.getBlockedBrowserOverrideWarning)('Claude Browser Attach', claudeBrowserExposure)
        : resolvedTarget === 'codex' && codexBrowserExposure
            ? (0, browser_1.getBlockedBrowserOverrideWarning)('Codex Browser Tools', codexBrowserExposure)
            : undefined;
    if (blockedBrowserOverrideWarning) {
        console.error((0, ui_1.warn)(blockedBrowserOverrideWarning));
    }
    if (resolvedTarget !== 'claude' && !targetBinaryInfo) {
        const displayName = targetAdapter?.displayName || resolvedTarget;
        console.error((0, ui_1.fail)(`${displayName} CLI not found.`));
        if (resolvedTarget === 'droid') {
            console.error((0, ui_1.info)('Install: npm i -g @factory/cli'));
        }
        else if (resolvedTarget === 'codex') {
            console.error((0, ui_1.info)('Install a recent @openai/codex build, then retry.'));
        }
        process.exit(1);
    }
    // Best-effort: prune stale Droid model entries at runtime so settings.json stays clean.
    if (resolvedTarget === 'droid') {
        try {
            const allProfiles = detector.getAllProfiles();
            const activeProfiles = allProfiles.settings.filter((name) => /^[a-zA-Z0-9._-]+$/.test(name));
            await (0, targets_1.pruneOrphanedModels)(activeProfiles);
        }
        catch (error) {
            console.error((0, ui_1.warn)(`[!] Droid prune skipped: ${error.message}`));
        }
    }
    // Per-target argument normalization
    let targetRemainingArgs = remainingArgs;
    let runtimeReasoningOverride;
    let nativeClaudeRemainingArgs = remainingArgs;
    if (resolvedTarget === 'droid') {
        try {
            const droidRoute = (0, droid_command_router_1.routeDroidCommandArgs)(remainingArgs);
            targetRemainingArgs = droidRoute.argsForDroid;
            if (droidRoute.mode === 'interactive') {
                const runtime = (0, cli_argument_parser_1.resolveRuntimeReasoningFlags)(remainingArgs, process.env['CCS_THINKING']);
                targetRemainingArgs = runtime.argsWithoutReasoningFlags;
                runtimeReasoningOverride = runtime.reasoningOverride;
            }
            else {
                if (droidRoute.duplicateReasoningDisplays.length > 0) {
                    console.error((0, ui_1.warn)(`[!] Multiple reasoning flags detected. Using first occurrence: ${droidRoute.reasoningSourceDisplay || '<first-flag>'}`));
                }
                if (droidRoute.autoPrependedExec && process.stdout.isTTY) {
                    console.error((0, ui_1.info)('Detected Droid exec-only flags. Routing as: droid exec <flags> [prompt]'));
                }
            }
        }
        catch (error) {
            if (error instanceof droid_reasoning_runtime_1.DroidReasoningFlagError || error instanceof droid_command_router_1.DroidCommandRouterError) {
                (0, cli_argument_parser_1.exitWithRuntimeReasoningFlagError)(error.message, {
                    codexAliasLevels: 'minimal|low|medium|high|xhigh',
                    includeDroidExecExample: true,
                });
            }
            throw error;
        }
    }
    else if (resolvedTarget === 'codex') {
        try {
            const runtime = (0, cli_argument_parser_1.resolveRuntimeReasoningFlags)(remainingArgs, process.env['CCS_THINKING']);
            targetRemainingArgs = runtime.argsWithoutReasoningFlags;
            const normalizedReasoning = (0, cli_argument_parser_1.normalizeCodexRuntimeReasoningOverride)(runtime.reasoningOverride);
            if (runtime.reasoningOverride !== undefined && !normalizedReasoning) {
                if (runtime.reasoningSource === 'flag') {
                    throw new droid_reasoning_runtime_1.DroidReasoningFlagError('Codex target supports reasoning levels only: minimal, low, medium, high, xhigh.', '--effort');
                }
                runtimeReasoningOverride = undefined;
            }
            else {
                runtimeReasoningOverride = normalizedReasoning;
            }
        }
        catch (error) {
            if (error instanceof droid_reasoning_runtime_1.DroidReasoningFlagError) {
                (0, cli_argument_parser_1.exitWithRuntimeReasoningFlagError)(error.message, {
                    codexAliasLevels: 'minimal|low|medium|high|xhigh',
                });
            }
            throw error;
        }
    }
    else if (resolvedTarget === 'claude' && (0, cli_argument_parser_1.shouldNormalizeNativeClaudeEffort)(profileInfo.type)) {
        nativeClaudeRemainingArgs = (0, cli_argument_parser_1.normalizeNativeClaudeEffortArgs)(remainingArgs);
    }
    return {
        profile,
        remainingArgs,
        profileInfo,
        resolvedTarget,
        claudeCli,
        targetAdapter,
        targetBinaryInfo,
        resolvedSettingsPath,
        resolvedSettings,
        resolvedCliproxyBridge,
        targetRemainingArgs,
        nativeClaudeRemainingArgs,
        runtimeReasoningOverride,
        codexRuntimeConfigOverrides,
        claudeBrowserExposure,
        codexBrowserExposure,
        claudeAttachConfig,
        detector,
    };
}
exports.resolveProfileAndTarget = resolveProfileAndTarget;
//# sourceMappingURL=profile-resolver.js.map