import CodexBarCore
import Foundation

extension SettingsStore {
    private var codexPersistedActiveSource: CodexActiveSource {
        self.providerConfig(for: .codex)?.codexActiveSource ?? .liveSystem
    }

    private enum ManagedCodexAccountStoreState {
        case none
        case selected(ManagedCodexAccount)
        case unreadable
    }

    private static func failClosedManagedCodexHomePath(fileManager: FileManager = .default) -> String {
        ManagedCodexHomeFactory.defaultRootURL(fileManager: fileManager)
            .appendingPathComponent("managed-store-unreadable", isDirectory: true)
            .path
    }

    private static func normalizedCodexProfileHomePaths(_ paths: [String]?) -> [String] {
        var seen: Set<String> = []
        var result: [String] = []
        for path in (paths ?? []).compactMap({ CodexHomeScope.normalizedHomePath($0) }) {
            guard seen.insert(path).inserted else { continue }
            result.append(path)
        }
        return result
    }

    private func loadManagedCodexAccounts() throws -> ManagedCodexAccountSet {
        #if DEBUG
        if CodexManagedRemoteHomeTestingOverride.isUnreadable(for: self) {
            throw CodexManagedRemoteHomeTestingOverrideError.unreadableManagedStore
        }
        if let override = CodexManagedRemoteHomeTestingOverride.account(for: self) {
            return ManagedCodexAccountSet(
                version: FileManagedCodexAccountStore.currentVersion,
                accounts: [override])
        }
        let store = if let storeURL = CodexManagedRemoteHomeTestingOverride.managedStoreURL(for: self) {
            FileManagedCodexAccountStore(fileURL: storeURL)
        } else {
            FileManagedCodexAccountStore()
        }
        #else
        let store = FileManagedCodexAccountStore()
        #endif

        return try store.loadAccounts()
    }

    private func managedCodexAccountStoreState(
        activeSource: CodexActiveSource? = nil) -> ManagedCodexAccountStoreState
    {
        let source = activeSource ?? self.codexResolvedActiveSource
        guard case let .managedAccount(id) = source else {
            return .none
        }
        do {
            let accounts = try self.loadManagedCodexAccounts()
            guard let account = accounts.account(id: id)
            else {
                return .none
            }
            return .selected(account)
        } catch {
            return .unreadable
        }
    }

    var activeManagedCodexAccount: ManagedCodexAccount? {
        guard case let .selected(account) = self.managedCodexAccountStoreState() else {
            return nil
        }
        return account
    }

    var activeManagedCodexRemoteHomePath: String? {
        self.managedCodexRemoteHomePath(forActiveSource: self.codexResolvedActiveSource)
    }

    func liveSystemCodexHomePath(forActiveSource source: CodexActiveSource) -> String? {
        guard source == .liveSystem else {
            return nil
        }
        let path = self.codexAccountReconciliationSnapshot(activeSourceOverride: source)
            .liveSystemAccount?.codexHomePath.trimmingCharacters(in: .whitespacesAndNewlines)
        guard let path, !path.isEmpty else {
            return nil
        }
        return path
    }

    var codexProfileHomePaths: [String] {
        Self.normalizedCodexProfileHomePaths(
            self.configSnapshot.providerConfig(for: .codex)?.codexProfileHomePaths)
    }

    func profileCodexHomePath(forActiveSource source: CodexActiveSource) -> String? {
        guard case let .profileHome(path) = source else {
            return nil
        }
        guard let normalizedPath = CodexHomeScope.normalizedHomePath(path),
              self.codexProfileHomePaths.contains(normalizedPath)
        else {
            return nil
        }
        return normalizedPath
    }

    func managedCodexRemoteHomePath(forActiveSource source: CodexActiveSource) -> String? {
        guard case let .managedAccount(id) = source else {
            return nil
        }

        #if DEBUG
        if let override = CodexManagedRemoteHomeTestingOverride.homePath(for: self) {
            return override
        }
        #endif

        do {
            let accounts = try self.loadManagedCodexAccounts()
            // A selected managed source must never fall back to ambient ~/.codex.
            return accounts.account(id: id)?.managedHomePath ?? Self.failClosedManagedCodexHomePath()
        } catch {
            return Self.failClosedManagedCodexHomePath()
        }
    }

    var activeManagedCodexCookieCacheScope: CookieHeaderCache.Scope? {
        switch self.managedCodexAccountStoreState() {
        case let .selected(account):
            .managedAccount(account.id)
        case .unreadable:
            .managedStoreUnreadable
        case .none:
            nil
        }
    }

    var hasUnreadableManagedCodexAccountStore: Bool {
        self.codexAccountReconciliationSnapshot.hasUnreadableAddedAccountStore
    }

    var codexUsageDataSource: CodexUsageDataSource {
        get {
            let source = self.configSnapshot.providerConfig(for: .codex)?.source
            return Self.codexUsageDataSource(from: source)
        }
        set {
            let source: ProviderSourceMode? = switch newValue {
            case .auto: .auto
            case .oauth: .oauth
            case .cli: .cli
            }
            self.updateProviderConfig(provider: .codex) { entry in
                entry.source = source
            }
            self.logProviderModeChange(provider: .codex, field: "usageSource", value: newValue.rawValue)
        }
    }

    var codexActiveSource: CodexActiveSource {
        get {
            self.codexPersistedActiveSource
        }
        set {
            self.invalidateCodexAccountReconciliationSnapshotCache()
            self.cachedCodexAccountMenuProjection = nil
            self.updateProviderConfig(provider: .codex) { entry in
                entry.codexActiveSource = newValue
            }
        }
    }

    var codexResolvedActiveSource: CodexActiveSource {
        self.codexResolvedActiveSourceState.resolvedSource
    }

    var codexResolvedActiveSourceState: CodexResolvedActiveSource {
        CodexActiveSourceResolver.resolve(from: self.codexAccountReconciliationSnapshot)
    }

    @discardableResult
    func persistResolvedCodexActiveSourceCorrectionIfNeeded() -> Bool {
        let resolution = self.codexResolvedActiveSourceState
        guard resolution.requiresPersistenceCorrection else { return false }
        self.codexActiveSource = resolution.resolvedSource
        return true
    }

    @discardableResult
    func refreshCodexAccountReconciliationAfterManagedAccountsDidChange() -> Bool {
        self.invalidateCodexAccountReconciliationSnapshotCache()
        self.cachedCodexAccountMenuProjection = nil
        return self.persistResolvedCodexActiveSourceCorrectionIfNeeded()
    }

    var codexCookieHeader: String {
        get { self.configSnapshot.providerConfig(for: .codex)?.sanitizedCookieHeader ?? "" }
        set {
            // This is intentionally provider-scoped today. A per-managed-account manual cookie override would need
            // its own storage and UI semantics so editing one account's header does not silently rewrite another's.
            self.updateProviderConfig(provider: .codex) { entry in
                entry.cookieHeader = self.normalizedConfigValue(newValue)
            }
            self.logSecretUpdate(provider: .codex, field: "cookieHeader", value: newValue)
        }
    }

    var codexCookieSource: ProviderCookieSource {
        get {
            let resolved = self.resolvedCookieSource(provider: .codex, fallback: .auto)
            return self.openAIWebAccessEnabled ? resolved : .off
        }
        set {
            self.updateProviderConfig(provider: .codex) { entry in
                entry.cookieSource = newValue
            }
            self.logProviderModeChange(provider: .codex, field: "cookieSource", value: newValue.rawValue)
            self.openAIWebAccessEnabled = newValue.isEnabled
        }
    }

    func ensureCodexCookieLoaded() {}
}

extension SettingsStore {
    private static var codexAccountReconciliationSnapshotCacheInterval: TimeInterval {
        #if DEBUG
        if let codexAccountReconciliationSnapshotCacheIntervalOverrideForTesting {
            return codexAccountReconciliationSnapshotCacheIntervalOverrideForTesting
        }
        #endif
        return self.isRunningTests ? 0 : self.productionCodexAccountReconciliationSnapshotCacheInterval
    }

    func invalidateCodexAccountReconciliationSnapshotCache() {
        self.cachedCodexAccountReconciliationSnapshot = nil
        self.codexAccountReconciliationGeneration &+= 1
    }

    var codexAccountReconciliationSnapshot: CodexAccountReconciliationSnapshot {
        self.codexAccountReconciliationSnapshot(activeSourceOverride: nil)
    }

    func codexAccountReconciliationSnapshot(
        activeSourceOverride: CodexActiveSource?) -> CodexAccountReconciliationSnapshot
    {
        let activeSource = activeSourceOverride ?? self.codexPersistedActiveSource
        let cacheInterval = Self.codexAccountReconciliationSnapshotCacheInterval
        let now = Date()
        if cacheInterval > 0,
           let cached = self.cachedCodexAccountReconciliationSnapshot,
           cached.activeSource == activeSource,
           now.timeIntervalSince(cached.loadedAt) < cacheInterval
        {
            return cached.snapshot
        }

        let snapshot = self.codexAccountSnapshotLoader(activeSource: activeSource)()
        let loadedAt = Date()
        if cacheInterval > 0 {
            self.cachedCodexAccountReconciliationSnapshot = CachedCodexAccountReconciliationSnapshot(
                activeSource: activeSource,
                loadedAt: loadedAt,
                snapshot: snapshot)
        }
        if activeSource == self.codexPersistedActiveSource {
            self.cachedCodexAccountMenuProjection = CachedCodexAccountMenuProjection(
                activeSource: activeSource,
                loadedAt: loadedAt,
                projection: CodexVisibleAccountProjection.make(from: snapshot))
        }
        return snapshot
    }

    /// Menu rendering must stay side-effect free: no `auth.json` reads, JWT parsing, or fingerprint hashing.
    var codexVisibleAccountProjectionForMenuDisplay: CodexVisibleAccountProjection? {
        let activeSource = self.codexPersistedActiveSource
        guard let cached = self.cachedCodexAccountMenuProjection,
              cached.activeSource == activeSource
        else {
            return nil
        }
        return cached.projection
    }

    var codexAccountMenuProjectionNeedsRevalidation: Bool {
        let activeSource = self.codexPersistedActiveSource
        guard let cached = self.cachedCodexAccountMenuProjection,
              cached.activeSource == activeSource
        else {
            return true
        }
        return Date().timeIntervalSince(cached.loadedAt) >= Self.codexAccountReconciliationSnapshotCacheInterval
    }

    func revalidateCodexAccountMenuProjection() async -> CodexAccountMenuProjectionRevalidationResult {
        guard self.codexAccountMenuProjectionNeedsRevalidation else { return .skipped }

        let activeSource = self.codexPersistedActiveSource
        let generation = self.codexAccountReconciliationGeneration
        let loader = self.codexAccountSnapshotLoader(activeSource: activeSource)
        let snapshot = await Self.loadCodexAccountSnapshot(loader)

        guard generation == self.codexAccountReconciliationGeneration,
              activeSource == self.codexPersistedActiveSource
        else {
            return .discarded
        }

        let now = Date()
        let projection = CodexVisibleAccountProjection.make(from: snapshot)
        let previousProjection = self.cachedCodexAccountMenuProjection.flatMap { cached in
            cached.activeSource == activeSource ? cached.projection : nil
        }
        self.cachedCodexAccountMenuProjection = CachedCodexAccountMenuProjection(
            activeSource: activeSource,
            loadedAt: now,
            projection: projection)
        if Self.codexAccountReconciliationSnapshotCacheInterval > 0 {
            self.cachedCodexAccountReconciliationSnapshot = CachedCodexAccountReconciliationSnapshot(
                activeSource: activeSource,
                loadedAt: now,
                snapshot: snapshot)
        }
        return previousProjection == projection ? .unchanged : .updated
    }

    @concurrent
    private nonisolated static func loadCodexAccountSnapshot(
        _ loader: @escaping @Sendable () -> CodexAccountReconciliationSnapshot)
        async -> CodexAccountReconciliationSnapshot
    {
        loader()
    }

    var codexVisibleAccountProjection: CodexVisibleAccountProjection {
        CodexVisibleAccountProjection.make(from: self.codexAccountReconciliationSnapshot)
    }

    var codexVisibleAccounts: [CodexVisibleAccount] {
        self.codexVisibleAccountProjection.visibleAccounts
    }

    @discardableResult
    func selectCodexVisibleAccount(id: String) -> Bool {
        guard let source = self.codexSource(forVisibleAccountID: id) else { return false }
        self.invalidateCodexAccountReconciliationSnapshotCache()
        self.codexActiveSource = source
        return true
    }

    func selectDisplayedCodexVisibleAccount(_ account: CodexVisibleAccount) {
        // The row already carries the exact source it represented. Re-resolving its ID would synchronously
        // reload auth state from the menu click callback and can also fail after a stale snapshot is rendered.
        self.codexActiveSource = account.selectionSource
    }

    func selectAuthenticatedManagedCodexAccount(_ account: ManagedCodexAccount) {
        if let visibleAccountID = self.codexVisibleAccountProjection.visibleAccounts
            .first(where: { $0.storedAccountID == account.id })?
            .id,
            self.selectCodexVisibleAccount(id: visibleAccountID)
        {
            return
        }

        self.invalidateCodexAccountReconciliationSnapshotCache()
        self.codexActiveSource = .managedAccount(id: account.id)
        _ = self.persistResolvedCodexActiveSourceCorrectionIfNeeded()
    }

    func codexSource(forVisibleAccountID id: String) -> CodexActiveSource? {
        self.codexVisibleAccountProjection.source(forVisibleAccountID: id)
    }

    private func codexAccountSnapshotLoader(
        activeSource: CodexActiveSource) -> @Sendable () -> CodexAccountReconciliationSnapshot
    {
        #if DEBUG
        if let loader = self._test_codexAccountSnapshotLoader {
            return { loader(activeSource) }
        }
        #endif
        let reconciler = self.codexAccountReconciler(activeSource: activeSource)
        return { reconciler.loadSnapshot() }
    }

    private func codexAccountReconciler(activeSource: CodexActiveSource) -> DefaultCodexAccountReconciler {
        let baseEnvironment = self.codexReconciliationEnvironment()
        #if DEBUG
        let liveSystemAccountOverride = CodexManagedRemoteHomeTestingOverride.liveSystemAccount(for: self)
        let reconciliationEnvironmentOverride = CodexManagedRemoteHomeTestingOverride
            .reconciliationEnvironment(for: self)
        let managedAccountOverride = CodexManagedRemoteHomeTestingOverride.account(for: self)
        let managedStoreURLOverride = CodexManagedRemoteHomeTestingOverride.managedStoreURL(for: self)
        let unreadableStoreOverride = CodexManagedRemoteHomeTestingOverride.isUnreadable(for: self)
        guard CodexManagedRemoteHomeTestingOverride.hasAnyOverride(for: self) else {
            return DefaultCodexAccountReconciler(
                activeSource: activeSource,
                baseEnvironment: baseEnvironment,
                profileHomePaths: self.codexProfileHomePaths,
                managedEnvironmentBuilder: { environment, account in
                    CodexHomeScope.scopedEnvironment(base: environment, codexHome: account.managedHomePath)
                })
        }

        let storeLoader: @Sendable () throws -> ManagedCodexAccountSet
        if unreadableStoreOverride {
            storeLoader = { throw CodexManagedRemoteHomeTestingOverrideError.unreadableManagedStore }
        } else if let managedAccountOverride {
            let accounts = ManagedCodexAccountSet(
                version: FileManagedCodexAccountStore.currentVersion,
                accounts: [managedAccountOverride])
            storeLoader = { accounts }
        } else if let managedStoreURLOverride {
            let store = FileManagedCodexAccountStore(fileURL: managedStoreURLOverride)
            storeLoader = { try store.loadAccounts() }
        } else {
            let accounts = ManagedCodexAccountSet(
                version: FileManagedCodexAccountStore.currentVersion,
                accounts: [])
            storeLoader = { accounts }
        }

        return DefaultCodexAccountReconciler(
            storeLoader: storeLoader,
            systemObserver: CodexManagedRemoteHomeTestingSystemObserver(
                overrideAccount: liveSystemAccountOverride,
                usesInjectedEnvironment: reconciliationEnvironmentOverride != nil),
            activeSource: activeSource,
            baseEnvironment: baseEnvironment,
            profileHomePaths: self.codexProfileHomePaths,
            managedEnvironmentBuilder: { environment, account in
                CodexHomeScope.scopedEnvironment(base: environment, codexHome: account.managedHomePath)
            })
        #else
        return DefaultCodexAccountReconciler(
            activeSource: activeSource,
            baseEnvironment: baseEnvironment,
            profileHomePaths: self.codexProfileHomePaths,
            managedEnvironmentBuilder: { environment, account in
                CodexHomeScope.scopedEnvironment(base: environment, codexHome: account.managedHomePath)
            })
        #endif
    }

    private func codexReconciliationEnvironment() -> [String: String] {
        #if DEBUG
        if let override = CodexManagedRemoteHomeTestingOverride.reconciliationEnvironment(for: self) {
            return override
        }
        #endif
        return ProcessInfo.processInfo.environment
    }
}

#if DEBUG
private enum CodexManagedRemoteHomeTestingOverride {
    private struct Override {
        var account: ManagedCodexAccount?
        var homePath: String?
        var unreadableStore: Bool = false
        var managedStoreURL: URL?
        var liveSystemAccount: ObservedSystemCodexAccount?
        var reconciliationEnvironment: [String: String]?

        var isEmpty: Bool {
            self.account == nil && self.homePath == nil && self.unreadableStore == false && self
                .managedStoreURL == nil && self.liveSystemAccount == nil && self
                .reconciliationEnvironment == nil
        }
    }

    private final class Entry {
        weak var settings: SettingsStore?
        var overrideValue: Override

        init(settings: SettingsStore, overrideValue: Override) {
            self.settings = settings
            self.overrideValue = overrideValue
        }
    }

    @MainActor
    private static var values: [ObjectIdentifier: Entry] = [:]

    @MainActor
    private static func entry(for settings: SettingsStore) -> Entry? {
        let key = ObjectIdentifier(settings)
        guard let entry = self.values[key] else { return nil }
        guard let storedSettings = entry.settings, storedSettings === settings else {
            self.values.removeValue(forKey: key)
            return nil
        }
        return entry
    }

    @MainActor
    static func account(for settings: SettingsStore) -> ManagedCodexAccount? {
        self.entry(for: settings)?.overrideValue.account
    }

    @MainActor
    static func setAccount(_ account: ManagedCodexAccount?, for settings: SettingsStore) {
        let key = ObjectIdentifier(settings)
        var override = self.entry(for: settings)?.overrideValue ?? Override()
        override.account = account
        if override.isEmpty {
            self.values.removeValue(forKey: key)
        } else {
            self.values[key] = Entry(settings: settings, overrideValue: override)
        }
    }

    @MainActor
    static func homePath(for settings: SettingsStore) -> String? {
        self.entry(for: settings)?.overrideValue.homePath
    }

    @MainActor
    static func setHomePath(_ value: String?, for settings: SettingsStore) {
        let key = ObjectIdentifier(settings)
        var override = self.entry(for: settings)?.overrideValue ?? Override()
        override.homePath = value
        if override.isEmpty {
            self.values.removeValue(forKey: key)
        } else {
            self.values[key] = Entry(settings: settings, overrideValue: override)
        }
    }

    @MainActor
    static func isUnreadable(for settings: SettingsStore) -> Bool {
        self.entry(for: settings)?.overrideValue.unreadableStore == true
    }

    @MainActor
    static func setUnreadable(_ value: Bool, for settings: SettingsStore) {
        let key = ObjectIdentifier(settings)
        var override = self.entry(for: settings)?.overrideValue ?? Override()
        override.unreadableStore = value
        if override.isEmpty {
            self.values.removeValue(forKey: key)
        } else {
            self.values[key] = Entry(settings: settings, overrideValue: override)
        }
    }

    @MainActor
    static func liveSystemAccount(for settings: SettingsStore) -> ObservedSystemCodexAccount? {
        self.entry(for: settings)?.overrideValue.liveSystemAccount
    }

    @MainActor
    static func managedStoreURL(for settings: SettingsStore) -> URL? {
        self.entry(for: settings)?.overrideValue.managedStoreURL
    }

    @MainActor
    static func setManagedStoreURL(_ value: URL?, for settings: SettingsStore) {
        let key = ObjectIdentifier(settings)
        var override = self.entry(for: settings)?.overrideValue ?? Override()
        override.managedStoreURL = value
        if override.isEmpty {
            self.values.removeValue(forKey: key)
        } else {
            self.values[key] = Entry(settings: settings, overrideValue: override)
        }
    }

    @MainActor
    static func setLiveSystemAccount(_ account: ObservedSystemCodexAccount?, for settings: SettingsStore) {
        let key = ObjectIdentifier(settings)
        var override = self.entry(for: settings)?.overrideValue ?? Override()
        override.liveSystemAccount = account
        if override.isEmpty {
            self.values.removeValue(forKey: key)
        } else {
            self.values[key] = Entry(settings: settings, overrideValue: override)
        }
    }

    @MainActor
    static func reconciliationEnvironment(for settings: SettingsStore) -> [String: String]? {
        self.entry(for: settings)?.overrideValue.reconciliationEnvironment
    }

    @MainActor
    static func setReconciliationEnvironment(_ environment: [String: String]?, for settings: SettingsStore) {
        let key = ObjectIdentifier(settings)
        var override = self.entry(for: settings)?.overrideValue ?? Override()
        override.reconciliationEnvironment = environment
        if override.isEmpty {
            self.values.removeValue(forKey: key)
        } else {
            self.values[key] = Entry(settings: settings, overrideValue: override)
        }
    }

    @MainActor
    static func hasAnyOverride(for settings: SettingsStore) -> Bool {
        self.entry(for: settings)?.overrideValue.isEmpty == false
    }
}

private enum CodexManagedRemoteHomeTestingOverrideError: Error {
    case unreadableManagedStore
}

private struct CodexManagedRemoteHomeTestingSystemObserver: CodexSystemAccountObserving {
    let overrideAccount: ObservedSystemCodexAccount?
    let usesInjectedEnvironment: Bool

    func loadSystemAccount(environment: [String: String]) throws -> ObservedSystemCodexAccount? {
        if let overrideAccount {
            return overrideAccount
        }
        guard self.usesInjectedEnvironment else {
            return nil
        }
        return try DefaultCodexSystemAccountObserver().loadSystemAccount(environment: environment)
    }
}

extension SettingsStore {
    private func invalidateCodexAccountReconciliationCachesForTesting() {
        self.invalidateCodexAccountReconciliationSnapshotCache()
        self.cachedCodexAccountMenuProjection = nil
    }

    var _test_activeManagedCodexRemoteHomePath: String? {
        get { CodexManagedRemoteHomeTestingOverride.homePath(for: self) }
        set {
            self.invalidateCodexAccountReconciliationCachesForTesting()
            CodexManagedRemoteHomeTestingOverride.setHomePath(newValue, for: self)
        }
    }

    var _test_activeManagedCodexAccount: ManagedCodexAccount? {
        get { CodexManagedRemoteHomeTestingOverride.account(for: self) }
        set {
            self.invalidateCodexAccountReconciliationCachesForTesting()
            CodexManagedRemoteHomeTestingOverride.setAccount(newValue, for: self)
        }
    }

    var _test_unreadableManagedCodexAccountStore: Bool {
        get { CodexManagedRemoteHomeTestingOverride.isUnreadable(for: self) }
        set {
            self.invalidateCodexAccountReconciliationCachesForTesting()
            CodexManagedRemoteHomeTestingOverride.setUnreadable(newValue, for: self)
        }
    }

    var _test_managedCodexAccountStoreURL: URL? {
        get { CodexManagedRemoteHomeTestingOverride.managedStoreURL(for: self) }
        set {
            self.invalidateCodexAccountReconciliationCachesForTesting()
            CodexManagedRemoteHomeTestingOverride.setManagedStoreURL(newValue, for: self)
        }
    }

    var _test_liveSystemCodexAccount: ObservedSystemCodexAccount? {
        get { CodexManagedRemoteHomeTestingOverride.liveSystemAccount(for: self) }
        set {
            self.invalidateCodexAccountReconciliationCachesForTesting()
            CodexManagedRemoteHomeTestingOverride.setLiveSystemAccount(newValue, for: self)
        }
    }

    var _test_codexReconciliationEnvironment: [String: String]? {
        get { CodexManagedRemoteHomeTestingOverride.reconciliationEnvironment(for: self) }
        set {
            self.invalidateCodexAccountReconciliationCachesForTesting()
            CodexManagedRemoteHomeTestingOverride.setReconciliationEnvironment(newValue, for: self)
        }
    }
}
#endif

extension SettingsStore {
    func codexSettingsSnapshot(
        tokenOverride: TokenAccountOverride?,
        activeSourceOverride: CodexActiveSource? = nil) -> ProviderSettingsSnapshot.CodexProviderSettings
    {
        let reconciliationSnapshot = self.codexAccountReconciliationSnapshot(
            activeSourceOverride: activeSourceOverride)
        let resolvedActiveSource = CodexActiveSourceResolver.resolve(from: reconciliationSnapshot)
        return CodexProviderSettingsBuilder.make(input: CodexProviderSettingsBuilderInput(
            usageDataSource: self.codexUsageDataSource,
            cookieSource: self.codexSnapshotCookieSource(tokenOverride: tokenOverride),
            manualCookieHeader: self.codexSnapshotCookieHeader(tokenOverride: tokenOverride),
            reconciliationSnapshot: reconciliationSnapshot,
            resolvedActiveSource: resolvedActiveSource))
    }

    private static func codexUsageDataSource(from source: ProviderSourceMode?) -> CodexUsageDataSource {
        guard let source else { return .auto }
        switch source {
        case .auto, .web, .api:
            return .auto
        case .cli:
            return .cli
        case .oauth:
            return .oauth
        }
    }

    private func codexSnapshotCookieHeader(tokenOverride: TokenAccountOverride?) -> String {
        let fallback = self.codexCookieHeader
        guard let support = TokenAccountSupportCatalog.support(for: .codex),
              case .cookieHeader = support.injection
        else {
            return fallback
        }
        guard let account = ProviderTokenAccountSelection.selectedAccount(
            provider: .codex,
            settings: self,
            override: tokenOverride)
        else {
            return fallback
        }
        return TokenAccountSupportCatalog.normalizedCookieHeader(account.token, support: support)
    }

    private func codexSnapshotCookieSource(tokenOverride: TokenAccountOverride?) -> ProviderCookieSource {
        let fallback = self.codexCookieSource
        guard let support = TokenAccountSupportCatalog.support(for: .codex),
              support.requiresManualCookieSource
        else {
            return fallback
        }
        if self.tokenAccounts(for: .codex).isEmpty { return fallback }
        return .manual
    }
}
