import Foundation
import Testing
@testable import CodexBarCore

@Suite(.serialized)
// swiftlint:disable:next type_body_length
struct ClaudeOAuthCredentialsStoreTests {
    private func makeCredentialsData(accessToken: String, expiresAt: Date, refreshToken: String? = nil) -> Data {
        let millis = Int(expiresAt.timeIntervalSince1970 * 1000)
        let refreshField: String = {
            guard let refreshToken else { return "" }
            return ",\n            \"refreshToken\": \"\(refreshToken)\""
        }()
        let json = """
        {
          "claudeAiOauth": {
            "accessToken": "\(accessToken)",
            "expiresAt": \(millis),
            "scopes": ["user:profile"]\(refreshField)
          }
        }
        """
        return Data(json.utf8)
    }

    private func profileCacheKey(environment: [String: String] = [:]) -> KeychainCacheStore.Key {
        ClaudeOAuthCredentialsStore.cacheKeyForTesting(
            profileIdentifier: ClaudeOAuthCredentialsStore.credentialsProfileIdentifier(environment: environment))
    }

    @Test
    func `persistent reference hash stays stable across keychain metadata refresh`() {
        let first = ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprint(
            modifiedAt: 1,
            createdAt: 1,
            persistentRefHash: "opaque-ref")
        let refreshed = ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprint(
            modifiedAt: 2,
            createdAt: 1,
            persistentRefHash: "opaque-ref")

        let firstHash = ClaudeOAuthCredentialsStore.withClaudeKeychainOverridesForTesting(
            data: nil,
            fingerprint: first)
        {
            ClaudeOAuthCredentialsStore.claudeKeychainPersistentRefHashWithoutPrompt()
        }
        let refreshedHash = ClaudeOAuthCredentialsStore.withClaudeKeychainOverridesForTesting(
            data: nil,
            fingerprint: refreshed)
        {
            ClaudeOAuthCredentialsStore.claudeKeychainPersistentRefHashWithoutPrompt()
        }

        #expect(firstHash == "opaque-ref")
        #expect(refreshedHash == firstHash)
    }

    @Test
    func `safety isolates the default Claude credentials file`() {
        guard ProcessInfo.processInfo.environment[KeychainTestSafety.allowAccessEnvironmentKey] != "1" else {
            return
        }

        let defaultURL = FileManager.default.homeDirectoryForCurrentUser
            .appendingPathComponent(".claude/.credentials.json")
        #expect(ClaudeOAuthCredentialsStore.resolvedCredentialsURLForTesting != defaultURL)

        let overrideURL = FileManager.default.temporaryDirectory
            .appendingPathComponent("explicit-credentials.json")
        let resolvedOverride = ClaudeOAuthCredentialsStore.withCredentialsURLOverrideForTesting(overrideURL) {
            ClaudeOAuthCredentialsStore.resolvedCredentialsURLForTesting
        }
        #expect(resolvedOverride == overrideURL)
    }

    @Test
    func `safety isolates pending cache clear from the application suite`() throws {
        guard ProcessInfo.processInfo.environment[KeychainTestSafety.allowAccessEnvironmentKey] != "1" else {
            return
        }

        let domain = "ClaudeOAuthPendingCacheIsolationTests.\(UUID().uuidString)"
        let key = "ClaudeOAuthPendingCodexBarOAuthKeychainCacheClearV1"
        let tempDirectory = FileManager.default.temporaryDirectory
            .appendingPathComponent(UUID().uuidString, isDirectory: true)
        let defaults = try #require(UserDefaults(suiteName: domain))
        defer {
            defaults.removePersistentDomain(forName: domain)
            defaults.synchronize()
            try? FileManager.default.removeItem(at: tempDirectory)
            ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting()
        }

        let sentinel = "isolation-sentinel-\(UUID().uuidString)"
        defaults.set(sentinel, forKey: key)
        defaults.synchronize()
        let implicitStore = ClaudeOAuthPendingCacheClearUserDefaultsStore(
            domain: domain,
            key: key,
            lockURL: tempDirectory.appendingPathComponent("cache.lock"))

        // never-mode cache invalidation marks pending clear without an explicit store override.
        ClaudeOAuthCredentialsStore.withImplicitPendingCacheClearStoreOverrideForTesting(implicitStore) {
            ClaudeOAuthKeychainPromptPreference.withTaskOverrideForTesting(.never) {
                ClaudeOAuthCredentialsStore.invalidateCache()
            }
        }

        defaults.synchronize()
        #expect(defaults.string(forKey: key) == sentinel)
    }

    @Test
    func `safety isolates pending cache clear across isolation scopes`() {
        guard ProcessInfo.processInfo.environment[KeychainTestSafety.allowAccessEnvironmentKey] != "1" else {
            return
        }

        ClaudeOAuthCredentialsStore.withIsolatedMemoryCacheForTesting {
            ClaudeOAuthKeychainPromptPreference.withTaskOverrideForTesting(.never) {
                ClaudeOAuthCredentialsStore.invalidateCache()
            }
            #expect(ClaudeOAuthCredentialsStore.hasPendingCodexBarOAuthKeychainCacheClearForTesting)
        }

        // A fresh isolation scope must not inherit pending state from a prior scope.
        ClaudeOAuthCredentialsStore.withIsolatedMemoryCacheForTesting {
            #expect(!ClaudeOAuthCredentialsStore.hasPendingCodexBarOAuthKeychainCacheClearForTesting)
        }

        // Unscoped never-mode marks must also leave subsequent isolation scopes clean.
        ClaudeOAuthKeychainPromptPreference.withTaskOverrideForTesting(.never) {
            ClaudeOAuthCredentialsStore.invalidateCache()
        }
        ClaudeOAuthCredentialsStore.withIsolatedMemoryCacheForTesting {
            #expect(!ClaudeOAuthCredentialsStore.hasPendingCodexBarOAuthKeychainCacheClearForTesting)
        }
    }

    @Test
    func `loads from keychain cache before expired file`() throws {
        let service = "com.steipete.codexbar.cache.tests.\(UUID().uuidString)"
        try ProviderInteractionContext.$current.withValue(.background) {
            try KeychainCacheStore.withServiceOverrideForTesting(service) {
                try KeychainAccessGate.withTaskOverrideForTesting(false) {
                    KeychainCacheStore.setTestStoreForTesting(true)
                    defer { KeychainCacheStore.setTestStoreForTesting(false) }

                    ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting()
                    defer { ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting() }
                    try ClaudeOAuthCredentialsStore.withIsolatedCredentialsFileTrackingForTesting {
                        try ClaudeOAuthCredentialsStore.withIsolatedMemoryCacheForTesting {
                            let tempDir = FileManager.default.temporaryDirectory
                                .appendingPathComponent(UUID().uuidString, isDirectory: true)
                            try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true)
                            let fileURL = tempDir.appendingPathComponent("credentials.json")
                            try ClaudeOAuthCredentialsStore.withCredentialsURLOverrideForTesting(fileURL) {
                                let expiredData = self.makeCredentialsData(
                                    accessToken: "expired",
                                    expiresAt: Date(timeIntervalSinceNow: -3600))
                                try expiredData.write(to: fileURL)

                                let cachedData = self.makeCredentialsData(
                                    accessToken: "cached",
                                    expiresAt: Date(timeIntervalSinceNow: 3600))
                                let cacheEntry = ClaudeOAuthCredentialsStore.CacheEntry(
                                    data: cachedData,
                                    storedAt: Date())
                                let cacheKey = KeychainCacheStore.Key.oauth(provider: .claude)
                                ClaudeOAuthCredentialsStore.invalidateCache()
                                KeychainCacheStore.store(key: cacheKey, entry: cacheEntry)
                                defer { KeychainCacheStore.clear(key: cacheKey) }
                                _ = try ClaudeOAuthKeychainReadStrategyPreference.withTaskOverrideForTesting(
                                    .securityFramework)
                                {
                                    try ClaudeOAuthKeychainPromptPreference.withTaskOverrideForTesting(
                                        .onlyOnUserAction)
                                    {
                                        try ClaudeOAuthCredentialsStore.load(
                                            environment: [:],
                                            allowKeychainPrompt: false)
                                    }
                                }
                                // Re-store to cache after file check has marked file as "seen"
                                KeychainCacheStore.store(key: cacheKey, entry: cacheEntry)
                                let creds = try ClaudeOAuthKeychainReadStrategyPreference.withTaskOverrideForTesting(
                                    .securityFramework)
                                {
                                    try ClaudeOAuthKeychainPromptPreference.withTaskOverrideForTesting(
                                        .onlyOnUserAction)
                                    {
                                        try ClaudeOAuthCredentialsStore.load(
                                            environment: [:],
                                            allowKeychainPrompt: false)
                                    }
                                }

                                #expect(creds.accessToken == "cached")
                                #expect(creds.isExpired == false)
                            }
                        }
                    }
                }
            }
        }
    }

    @Test
    func `load record non interactive repair can be disabled`() throws {
        let service = "com.steipete.codexbar.cache.tests.\(UUID().uuidString)"
        try KeychainCacheStore.withServiceOverrideForTesting(service) {
            KeychainCacheStore.setTestStoreForTesting(true)
            defer { KeychainCacheStore.setTestStoreForTesting(false) }

            ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting()
            defer { ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting() }

            try ClaudeOAuthCredentialsStore.withIsolatedCredentialsFileTrackingForTesting {
                try ClaudeOAuthCredentialsStore.withIsolatedMemoryCacheForTesting {
                    // Ensure file-based lookup doesn't interfere (and avoid touching ~/.claude).
                    let tempDir = FileManager.default.temporaryDirectory
                        .appendingPathComponent(UUID().uuidString, isDirectory: true)
                    try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true)
                    let fileURL = tempDir.appendingPathComponent("credentials.json")
                    try ClaudeOAuthCredentialsStore.withCredentialsURLOverrideForTesting(fileURL) {
                        ClaudeOAuthCredentialsStore.invalidateCache()

                        let keychainData = self.makeCredentialsData(
                            accessToken: "claude-keychain",
                            expiresAt: Date(timeIntervalSinceNow: 3600))

                        // Simulate Claude Keychain containing creds, without querying the real Keychain.
                        try ProviderInteractionContext.$current.withValue(.userInitiated) {
                            try ClaudeOAuthCredentialsStore
                                .withClaudeKeychainOverridesForTesting(data: keychainData, fingerprint: nil) {
                                    // When repair is disabled, non-interactive loads should not consult Claude's
                                    // keychain data.
                                    do {
                                        _ = try ClaudeOAuthCredentialsStore.loadRecord(
                                            environment: [:],
                                            allowKeychainPrompt: false,
                                            respectKeychainPromptCooldown: true,
                                            allowClaudeKeychainRepairWithoutPrompt: false)
                                        Issue.record("Expected ClaudeOAuthCredentialsError.notFound")
                                    } catch let error as ClaudeOAuthCredentialsError {
                                        guard case .notFound = error else {
                                            Issue.record("Expected .notFound, got \(error)")
                                            return
                                        }
                                    }

                                    // With repair enabled, we should be able to seed from the "Claude keychain"
                                    // override.
                                    let record = try ClaudeOAuthCredentialsStore.loadRecord(
                                        environment: [:],
                                        allowKeychainPrompt: false,
                                        respectKeychainPromptCooldown: true,
                                        allowClaudeKeychainRepairWithoutPrompt: true)
                                    #expect(record.credentials.accessToken == "claude-keychain")
                                }
                        }
                    }
                }
            }
        }
    }

    @Test
    func `invalidates cache when credentials file changes`() throws {
        KeychainCacheStore.setTestStoreForTesting(true)
        defer { KeychainCacheStore.setTestStoreForTesting(false) }

        ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting()
        defer { ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting() }

        // Avoid interacting with the real Keychain in unit tests.
        try ClaudeOAuthCredentialsStore.withKeychainAccessOverrideForTesting(true) {
            try ClaudeOAuthCredentialsStore.withIsolatedCredentialsFileTrackingForTesting {
                try ClaudeOAuthCredentialsStore.withIsolatedMemoryCacheForTesting {
                    let tempDir = FileManager.default.temporaryDirectory
                        .appendingPathComponent(UUID().uuidString, isDirectory: true)
                    try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true)
                    let fileURL = tempDir.appendingPathComponent("credentials.json")
                    try ClaudeOAuthCredentialsStore.withCredentialsURLOverrideForTesting(fileURL) {
                        let first = self.makeCredentialsData(
                            accessToken: "first",
                            expiresAt: Date(timeIntervalSinceNow: 3600))
                        try first.write(to: fileURL)

                        let cacheKey = KeychainCacheStore.Key.oauth(provider: .claude)
                        let cacheEntry = ClaudeOAuthCredentialsStore.CacheEntry(data: first, storedAt: Date())
                        KeychainCacheStore.store(key: cacheKey, entry: cacheEntry)

                        _ = try ClaudeOAuthCredentialsStore.load(environment: [:])

                        let updated = self.makeCredentialsData(
                            accessToken: "second",
                            expiresAt: Date(timeIntervalSinceNow: 3600))
                        try updated.write(to: fileURL)

                        #expect(ClaudeOAuthCredentialsStore.invalidateCacheIfCredentialsFileChanged())
                        KeychainCacheStore.clear(key: cacheKey)

                        let creds = try ClaudeOAuthCredentialsStore.load(environment: [:])
                        #expect(creds.accessToken == "second")
                    }
                }
            }
        }
    }

    @Test
    func `returns expired file when no other sources`() throws {
        let service = "com.steipete.codexbar.cache.tests.\(UUID().uuidString)"
        try KeychainCacheStore.withServiceOverrideForTesting(service) {
            try KeychainAccessGate.withTaskOverrideForTesting(true) {
                KeychainCacheStore.setTestStoreForTesting(true)
                defer { KeychainCacheStore.setTestStoreForTesting(false) }

                try ClaudeOAuthCredentialsStore.withIsolatedMemoryCacheForTesting {
                    ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting()
                    defer { ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting() }

                    let tempDir = FileManager.default.temporaryDirectory
                        .appendingPathComponent(UUID().uuidString, isDirectory: true)
                    try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true)
                    let fileURL = tempDir.appendingPathComponent("credentials.json")
                    try ClaudeOAuthCredentialsStore.withCredentialsURLOverrideForTesting(fileURL) {
                        let expiredData = self.makeCredentialsData(
                            accessToken: "expired-only",
                            expiresAt: Date(timeIntervalSinceNow: -3600))
                        try expiredData.write(to: fileURL)

                        try ClaudeOAuthCredentialsStore.withKeychainAccessOverrideForTesting(true) {
                            ClaudeOAuthCredentialsStore.invalidateCache()
                            let creds = try ClaudeOAuthCredentialsStore.load(environment: [:])

                            #expect(creds.accessToken == "expired-only")
                            #expect(creds.isExpired == true)
                        }
                    }
                }
            }
        }
    }

    @Test
    func `load with auto refresh expired claude CLI owner throws delegated refresh`() async throws {
        let service = "com.steipete.codexbar.cache.tests.\(UUID().uuidString)"
        try await KeychainCacheStore.withServiceOverrideForTesting(service) {
            KeychainCacheStore.setTestStoreForTesting(true)
            defer { KeychainCacheStore.setTestStoreForTesting(false) }

            ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting()
            defer { ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting() }

            let tempDir = FileManager.default.temporaryDirectory
                .appendingPathComponent(UUID().uuidString, isDirectory: true)
            try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true)
            let fileURL = tempDir.appendingPathComponent("credentials.json")
            await ClaudeOAuthCredentialsStore.withCredentialsURLOverrideForTesting(fileURL) {
                await ClaudeOAuthCredentialsStore.withKeychainAccessOverrideForTesting(true) {
                    ClaudeOAuthCredentialsStore.invalidateCache()
                    let cacheKey = ClaudeOAuthCredentialsStore.cacheKeyForTesting(
                        profileIdentifier: ClaudeOAuthCredentialsStore.credentialsProfileIdentifier(
                            environment: [:]))
                    defer { KeychainCacheStore.clear(key: cacheKey) }

                    let expiredData = self.makeCredentialsData(
                        accessToken: "expired-claude-cli-owner",
                        expiresAt: Date(timeIntervalSinceNow: -3600),
                        refreshToken: "refresh-token")
                    KeychainCacheStore.store(
                        key: cacheKey,
                        entry: ClaudeOAuthCredentialsStore.CacheEntry(
                            data: expiredData,
                            storedAt: Date(),
                            owner: .claudeCLI))

                    do {
                        _ = try await ClaudeOAuthCredentialsStore.loadWithAutoRefresh(
                            environment: [:],
                            allowKeychainPrompt: false,
                            respectKeychainPromptCooldown: true)
                        Issue.record("Expected delegated refresh error for Claude CLI-owned credentials")
                    } catch let error as ClaudeOAuthCredentialsError {
                        guard case .refreshDelegatedToClaudeCLI = error else {
                            Issue.record("Expected .refreshDelegatedToClaudeCLI, got \(error)")
                            return
                        }
                    } catch {
                        Issue.record("Expected ClaudeOAuthCredentialsError, got \(error)")
                    }
                }
            }
        }
    }

    @Test
    func `load with auto refresh expired codexbar owner uses direct refresh path`() async throws {
        let service = "com.steipete.codexbar.cache.tests.\(UUID().uuidString)"
        try await KeychainCacheStore.withServiceOverrideForTesting(service) {
            KeychainCacheStore.setTestStoreForTesting(true)
            defer { KeychainCacheStore.setTestStoreForTesting(false) }

            ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting()
            defer { ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting() }

            let tempDir = FileManager.default.temporaryDirectory
                .appendingPathComponent(UUID().uuidString, isDirectory: true)
            try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true)
            let fileURL = tempDir.appendingPathComponent("credentials.json")
            // Isolate from the developer's ambient Claude config: a logged-in ~/.claude.json would
            // hand the refresh chain to the Claude CLI, and this test covers the CLI-absent path.
            let environment = [ClaudeConfigPaths.configDirectoryEnvironmentKey: tempDir.path]
            await ClaudeOAuthCredentialsStore.withCredentialsURLOverrideForTesting(fileURL) {
                await ClaudeOAuthCredentialsStore.withKeychainAccessOverrideForTesting(true) {
                    ClaudeOAuthCredentialsStore.invalidateCache()
                    let cacheKey = ClaudeOAuthCredentialsStore.cacheKeyForTesting(
                        profileIdentifier: ClaudeOAuthCredentialsStore.credentialsProfileIdentifier(
                            environment: environment))
                    defer { KeychainCacheStore.clear(key: cacheKey) }

                    let expiredData = self.makeCredentialsData(
                        accessToken: "expired-codexbar-owner",
                        expiresAt: Date(timeIntervalSinceNow: -3600),
                        refreshToken: "refresh-token")
                    KeychainCacheStore.store(
                        key: cacheKey,
                        entry: ClaudeOAuthCredentialsStore.CacheEntry(
                            data: expiredData,
                            storedAt: Date(),
                            owner: .codexbar))

                    await ClaudeOAuthRefreshFailureGate.$shouldAttemptOverride.withValue(false) {
                        do {
                            _ = try await ClaudeOAuthCredentialsStore.loadWithAutoRefresh(
                                environment: environment,
                                allowKeychainPrompt: false,
                                respectKeychainPromptCooldown: true)
                            Issue.record("Expected refresh failure for CodexBar-owned direct refresh path")
                        } catch let error as ClaudeOAuthCredentialsError {
                            guard case .refreshFailed = error else {
                                Issue.record("Expected .refreshFailed, got \(error)")
                                return
                            }
                        } catch {
                            Issue.record("Expected ClaudeOAuthCredentialsError, got \(error)")
                        }
                    }
                }
            }
        }
    }

    @Test
    func `load record legacy cache entry without owner defaults to claude CLI owner`() throws {
        KeychainCacheStore.setTestStoreForTesting(true)
        defer { KeychainCacheStore.setTestStoreForTesting(false) }

        ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting()
        defer { ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting() }

        let tempDir = FileManager.default.temporaryDirectory
            .appendingPathComponent(UUID().uuidString, isDirectory: true)
        try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true)
        let fileURL = tempDir.appendingPathComponent("credentials.json")
        try ClaudeOAuthCredentialsStore.withIsolatedMemoryCacheForTesting {
            try ClaudeOAuthCredentialsStore.withCredentialsURLOverrideForTesting(fileURL) {
                try ClaudeOAuthCredentialsStore.withKeychainAccessOverrideForTesting(true) {
                    ClaudeOAuthCredentialsStore.invalidateCache()
                    let cacheKey = KeychainCacheStore.Key.oauth(provider: .claude)
                    defer { KeychainCacheStore.clear(key: cacheKey) }

                    let validData = self.makeCredentialsData(
                        accessToken: "legacy-owner",
                        expiresAt: Date(timeIntervalSinceNow: 3600),
                        refreshToken: "refresh-token")
                    KeychainCacheStore.store(
                        key: cacheKey,
                        entry: ClaudeOAuthCredentialsStore.CacheEntry(
                            data: validData,
                            storedAt: Date()))

                    let record = try ClaudeOAuthCredentialsStore.loadRecord(
                        environment: [:],
                        allowKeychainPrompt: false,
                        respectKeychainPromptCooldown: true)
                    #expect(record.owner == .claudeCLI)
                    #expect(record.source == .cacheKeychain)
                }
            }
        }
    }

    @Test
    func `has cached credentials returns false for expired unrefreshable codexbar cache entry`() throws {
        KeychainCacheStore.setTestStoreForTesting(true)
        defer { KeychainCacheStore.setTestStoreForTesting(false) }

        ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting()
        defer { ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting() }

        let tempDir = FileManager.default.temporaryDirectory
            .appendingPathComponent(UUID().uuidString, isDirectory: true)
        try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true)
        let fileURL = tempDir.appendingPathComponent("credentials.json")
        ClaudeOAuthCredentialsStore.withCredentialsURLOverrideForTesting(fileURL) {
            ClaudeOAuthCredentialsStore.invalidateCache()

            let expiredData = self.makeCredentialsData(
                accessToken: "expired-no-refresh",
                expiresAt: Date(timeIntervalSinceNow: -3600),
                refreshToken: nil)
            let cacheEntry = ClaudeOAuthCredentialsStore.CacheEntry(
                data: expiredData,
                storedAt: Date(),
                owner: .codexbar)
            let cacheKey = KeychainCacheStore.Key.oauth(provider: .claude)
            KeychainCacheStore.store(key: cacheKey, entry: cacheEntry)

            #expect(ClaudeOAuthCredentialsStore.hasCachedCredentials() == false)
        }
    }

    @Test
    func `has cached credentials returns true for expired refreshable cache entry`() throws {
        KeychainCacheStore.setTestStoreForTesting(true)
        defer { KeychainCacheStore.setTestStoreForTesting(false) }

        ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting()
        defer { ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting() }

        let tempDir = FileManager.default.temporaryDirectory
            .appendingPathComponent(UUID().uuidString, isDirectory: true)
        try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true)
        let fileURL = tempDir.appendingPathComponent("credentials.json")
        ClaudeOAuthCredentialsStore.withCredentialsURLOverrideForTesting(fileURL) {
            ClaudeOAuthCredentialsStore.invalidateCache()

            let expiredData = self.makeCredentialsData(
                accessToken: "expired-refreshable",
                expiresAt: Date(timeIntervalSinceNow: -3600),
                refreshToken: "refresh")
            let cacheEntry = ClaudeOAuthCredentialsStore.CacheEntry(data: expiredData, storedAt: Date())
            let cacheKey = KeychainCacheStore.Key.oauth(provider: .claude)
            KeychainCacheStore.store(key: cacheKey, entry: cacheEntry)

            #expect(ClaudeOAuthCredentialsStore.hasCachedCredentials() == true)
        }
    }

    @Test
    func `has cached credentials returns true for expired claude CLI backed credentials file`() throws {
        KeychainCacheStore.setTestStoreForTesting(true)
        defer { KeychainCacheStore.setTestStoreForTesting(false) }

        ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting()
        defer { ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting() }

        let tempDir = FileManager.default.temporaryDirectory
            .appendingPathComponent(UUID().uuidString, isDirectory: true)
        try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true)
        let fileURL = tempDir.appendingPathComponent("credentials.json")
        try ClaudeOAuthCredentialsStore.withCredentialsURLOverrideForTesting(fileURL) {
            ClaudeOAuthCredentialsStore.invalidateCache()

            let expiredData = self.makeCredentialsData(
                accessToken: "expired-file-no-refresh",
                expiresAt: Date(timeIntervalSinceNow: -3600),
                refreshToken: nil)
            try expiredData.write(to: fileURL)

            #expect(ClaudeOAuthCredentialsStore.hasCachedCredentials() == true)
        }
    }

    @Test
    func `syncs cache when claude keychain fingerprint changes and token differs`() throws {
        let service = "com.steipete.codexbar.cache.tests.\(UUID().uuidString)"
        try KeychainCacheStore.withServiceOverrideForTesting(service) {
            try KeychainAccessGate.withTaskOverrideForTesting(false) {
                KeychainCacheStore.setTestStoreForTesting(true)
                defer { KeychainCacheStore.setTestStoreForTesting(false) }

                ClaudeOAuthKeychainAccessGate.resetForTesting()
                defer { ClaudeOAuthKeychainAccessGate.resetForTesting() }

                ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting()
                defer { ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting() }

                let tempDir = FileManager.default.temporaryDirectory
                    .appendingPathComponent(UUID().uuidString, isDirectory: true)
                try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true)
                let fileURL = tempDir.appendingPathComponent("credentials.json")
                try ClaudeOAuthCredentialsStore.withCredentialsURLOverrideForTesting(fileURL) {
                    ClaudeOAuthCredentialsStore.invalidateCache()
                    ClaudeOAuthCredentialsStore._resetClaudeKeychainChangeTrackingForTesting()
                    defer {
                        ClaudeOAuthCredentialsStore.invalidateCache()
                        ClaudeOAuthCredentialsStore._resetClaudeKeychainChangeTrackingForTesting()
                    }

                    // Avoid cross-suite interference from UserDefaults fingerprint persistence.
                    let fingerprintStore = ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprintStore()

                    let cacheKey = ClaudeOAuthCredentialsStore.cacheKeyForTesting(
                        profileIdentifier: ClaudeOAuthCredentialsStore.credentialsProfileIdentifier(
                            environment: [:]))
                    let cachedData = self.makeCredentialsData(
                        accessToken: "cached-token",
                        expiresAt: Date(timeIntervalSinceNow: 3600))
                    KeychainCacheStore.store(
                        key: cacheKey,
                        entry: ClaudeOAuthCredentialsStore.CacheEntry(data: cachedData, storedAt: Date()))

                    let fingerprint1 = ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprint(
                        modifiedAt: 1,
                        createdAt: 1,
                        persistentRefHash: "ref1")

                    let first = try ProviderInteractionContext.$current.withValue(.userInitiated) {
                        try ClaudeOAuthCredentialsStore.withClaudeKeychainFingerprintStoreOverrideForTesting(
                            fingerprintStore)
                        {
                            try ClaudeOAuthKeychainAccessGate.withShouldAllowPromptOverrideForTesting(true) {
                                try ClaudeOAuthCredentialsStore.withClaudeKeychainOverridesForTesting(
                                    data: cachedData,
                                    fingerprint: fingerprint1)
                                {
                                    try ClaudeOAuthCredentialsStore.load(environment: [:], allowKeychainPrompt: false)
                                }
                            }
                        }
                    }
                    #expect(first.accessToken == "cached-token")
                    #expect(fingerprintStore.fingerprint == fingerprint1)

                    ClaudeOAuthCredentialsStore._resetClaudeKeychainChangeThrottleForTesting()

                    let fingerprint2 = ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprint(
                        modifiedAt: 2,
                        createdAt: 2,
                        persistentRefHash: "ref2")

                    let keychainData = self.makeCredentialsData(
                        accessToken: "keychain-token",
                        expiresAt: Date(timeIntervalSinceNow: 3600))

                    let second = try ProviderInteractionContext.$current.withValue(.userInitiated) {
                        try ClaudeOAuthCredentialsStore.withClaudeKeychainFingerprintStoreOverrideForTesting(
                            fingerprintStore)
                        {
                            try ClaudeOAuthKeychainAccessGate.withShouldAllowPromptOverrideForTesting(true) {
                                try ClaudeOAuthCredentialsStore.withClaudeKeychainOverridesForTesting(
                                    data: keychainData,
                                    fingerprint: fingerprint2)
                                {
                                    try ClaudeOAuthCredentialsStore.load(environment: [:], allowKeychainPrompt: false)
                                }
                            }
                        }
                    }
                    #expect(second.accessToken == "keychain-token")
                    #expect(fingerprintStore.fingerprint == fingerprint2)

                    switch KeychainCacheStore.load(key: cacheKey, as: ClaudeOAuthCredentialsStore.CacheEntry.self) {
                    case let .found(entry):
                        let parsed = try ClaudeOAuthCredentials.parse(data: entry.data)
                        #expect(parsed.accessToken == "keychain-token")
                    default:
                        #expect(Bool(false))
                    }
                }
            }
        }
    }

    @Test
    func `does not sync in background when cache valid and prompt mode only on user action`() throws {
        let service = "com.steipete.codexbar.cache.tests.\(UUID().uuidString)"
        try KeychainCacheStore.withServiceOverrideForTesting(service) {
            try KeychainAccessGate.withTaskOverrideForTesting(false) {
                KeychainCacheStore.setTestStoreForTesting(true)
                defer { KeychainCacheStore.setTestStoreForTesting(false) }

                ClaudeOAuthKeychainAccessGate.resetForTesting()
                defer { ClaudeOAuthKeychainAccessGate.resetForTesting() }

                ClaudeOAuthCredentialsStore.invalidateCache()
                ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting()
                defer {
                    ClaudeOAuthCredentialsStore.invalidateCache()
                    ClaudeOAuthCredentialsStore._resetCredentialsFileTrackingForTesting()
                    ClaudeOAuthCredentialsStore._resetClaudeKeychainChangeTrackingForTesting()
                }

                let tempDir = FileManager.default.temporaryDirectory
                    .appendingPathComponent(UUID().uuidString, isDirectory: true)
                try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true)
                let fileURL = tempDir.appendingPathComponent("credentials.json")

                try ClaudeOAuthCredentialsStore.withCredentialsURLOverrideForTesting(fileURL) {
                    ClaudeOAuthCredentialsStore._resetClaudeKeychainChangeTrackingForTesting()

                    let fingerprintStore = ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprintStore()
                    let fingerprint1 = ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprint(
                        modifiedAt: 1,
                        createdAt: 1,
                        persistentRefHash: "ref1")
                    fingerprintStore.fingerprint = fingerprint1

                    let cacheKey = ClaudeOAuthCredentialsStore.cacheKeyForTesting(
                        profileIdentifier: ClaudeOAuthCredentialsStore.credentialsProfileIdentifier(
                            environment: [:]))
                    let cachedData = self.makeCredentialsData(
                        accessToken: "cached-token",
                        expiresAt: Date(timeIntervalSinceNow: 3600))
                    KeychainCacheStore.store(
                        key: cacheKey,
                        entry: ClaudeOAuthCredentialsStore.CacheEntry(
                            data: cachedData,
                            storedAt: Date(),
                            owner: .claudeCLI))

                    ClaudeOAuthCredentialsStore._resetClaudeKeychainChangeThrottleForTesting()

                    let fingerprint2 = ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprint(
                        modifiedAt: 2,
                        createdAt: 2,
                        persistentRefHash: "ref2")
                    let keychainData = self.makeCredentialsData(
                        accessToken: "keychain-token",
                        expiresAt: Date(timeIntervalSinceNow: 3600))

                    let creds = try ClaudeOAuthKeychainPromptPreference.withTaskOverrideForTesting(.onlyOnUserAction) {
                        try ProviderInteractionContext.$current.withValue(.background) {
                            try ClaudeOAuthCredentialsStore.withClaudeKeychainFingerprintStoreOverrideForTesting(
                                fingerprintStore)
                            {
                                try ClaudeOAuthCredentialsStore.withClaudeKeychainOverridesForTesting(
                                    data: keychainData,
                                    fingerprint: fingerprint2)
                                {
                                    try ClaudeOAuthCredentialsStore.load(environment: [:], allowKeychainPrompt: false)
                                }
                            }
                        }
                    }

                    #expect(creds.accessToken == "cached-token")
                    #expect(fingerprintStore.fingerprint == fingerprint1)

                    switch KeychainCacheStore.load(key: cacheKey, as: ClaudeOAuthCredentialsStore.CacheEntry.self) {
                    case let .found(entry):
                        let parsed = try ClaudeOAuthCredentials.parse(data: entry.data)
                        #expect(parsed.accessToken == "cached-token")
                    default:
                        #expect(Bool(false))
                    }
                }
            }
        }
    }

    @Test
    func `does not sync when claude keychain fingerprint unchanged`() throws {
        KeychainCacheStore.setTestStoreForTesting(true)
        defer { KeychainCacheStore.setTestStoreForTesting(false) }

        try ClaudeOAuthCredentialsStore.withIsolatedMemoryCacheForTesting {
            try ClaudeOAuthCredentialsStore.withIsolatedCredentialsFileTrackingForTesting {
                ClaudeOAuthCredentialsStore.invalidateCache()
                ClaudeOAuthCredentialsStore._resetClaudeKeychainChangeTrackingForTesting()
                defer {
                    ClaudeOAuthCredentialsStore.invalidateCache()
                    ClaudeOAuthCredentialsStore._resetClaudeKeychainChangeTrackingForTesting()
                }

                let cacheKey = ClaudeOAuthCredentialsStore.cacheKeyForTesting(
                    profileIdentifier: ClaudeOAuthCredentialsStore.credentialsProfileIdentifier(
                        environment: [:]))
                let cachedData = self.makeCredentialsData(
                    accessToken: "cached-token",
                    expiresAt: Date(timeIntervalSinceNow: 3600))
                KeychainCacheStore.store(
                    key: cacheKey,
                    entry: ClaudeOAuthCredentialsStore.CacheEntry(data: cachedData, storedAt: Date()))

                let fingerprint = ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprint(
                    modifiedAt: 1,
                    createdAt: 1,
                    persistentRefHash: "ref1")
                let first = try ClaudeOAuthCredentialsStore.withClaudeKeychainOverridesForTesting(
                    data: cachedData,
                    fingerprint: fingerprint,
                    operation: {
                        try ClaudeOAuthCredentialsStore.load(environment: [:], allowKeychainPrompt: false)
                    })
                #expect(first.accessToken == "cached-token")

                ClaudeOAuthCredentialsStore._resetClaudeKeychainChangeThrottleForTesting()
                let keychainData = self.makeCredentialsData(
                    accessToken: "keychain-token",
                    expiresAt: Date(timeIntervalSinceNow: 3600))
                let second = try ClaudeOAuthCredentialsStore.withClaudeKeychainOverridesForTesting(
                    data: keychainData,
                    fingerprint: fingerprint,
                    operation: {
                        try ClaudeOAuthCredentialsStore.load(environment: [:], allowKeychainPrompt: false)
                    })
                #expect(second.accessToken == "cached-token")

                switch KeychainCacheStore.load(key: cacheKey, as: ClaudeOAuthCredentialsStore.CacheEntry.self) {
                case let .found(entry):
                    let parsed = try ClaudeOAuthCredentials.parse(data: entry.data)
                    #expect(parsed.accessToken == "cached-token")
                default:
                    #expect(Bool(false))
                }
            }
        }
    }

    @Test
    func `does not sync when keychain credentials expired but cache valid`() throws {
        KeychainCacheStore.setTestStoreForTesting(true)
        defer { KeychainCacheStore.setTestStoreForTesting(false) }

        try ClaudeOAuthCredentialsStore.withIsolatedMemoryCacheForTesting {
            try ClaudeOAuthCredentialsStore.withIsolatedCredentialsFileTrackingForTesting {
                ClaudeOAuthCredentialsStore.invalidateCache()
                ClaudeOAuthCredentialsStore._resetClaudeKeychainChangeTrackingForTesting()
                defer {
                    ClaudeOAuthCredentialsStore.invalidateCache()
                    ClaudeOAuthCredentialsStore._resetClaudeKeychainChangeTrackingForTesting()
                }

                let cacheKey = ClaudeOAuthCredentialsStore.cacheKeyForTesting(
                    profileIdentifier: ClaudeOAuthCredentialsStore.credentialsProfileIdentifier(
                        environment: [:]))
                let cachedData = self.makeCredentialsData(
                    accessToken: "cached-token",
                    expiresAt: Date(timeIntervalSinceNow: 3600))
                KeychainCacheStore.store(
                    key: cacheKey,
                    entry: ClaudeOAuthCredentialsStore.CacheEntry(data: cachedData, storedAt: Date()))

                let first = try ClaudeOAuthCredentialsStore.withClaudeKeychainOverridesForTesting(
                    data: cachedData,
                    fingerprint: ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprint(
                        modifiedAt: 1,
                        createdAt: 1,
                        persistentRefHash: "ref1"),
                    operation: {
                        try ClaudeOAuthCredentialsStore.load(environment: [:], allowKeychainPrompt: false)
                    })
                #expect(first.accessToken == "cached-token")

                ClaudeOAuthCredentialsStore._resetClaudeKeychainChangeThrottleForTesting()

                let expiredKeychainData = self.makeCredentialsData(
                    accessToken: "expired-keychain-token",
                    expiresAt: Date(timeIntervalSinceNow: -3600))
                let second = try ClaudeOAuthCredentialsStore.withClaudeKeychainOverridesForTesting(
                    data: expiredKeychainData,
                    fingerprint: ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprint(
                        modifiedAt: 2,
                        createdAt: 2,
                        persistentRefHash: "ref2"),
                    operation: {
                        try ClaudeOAuthCredentialsStore.load(environment: [:], allowKeychainPrompt: false)
                    })
                #expect(second.accessToken == "cached-token")

                switch KeychainCacheStore.load(key: cacheKey, as: ClaudeOAuthCredentialsStore.CacheEntry.self) {
                case let .found(entry):
                    let parsed = try ClaudeOAuthCredentials.parse(data: entry.data)
                    #expect(parsed.accessToken == "cached-token")
                default:
                    #expect(Bool(false))
                }
            }
        }
    }

    @Test
    func `respects prompt cooldown gate when disabled prompting`() throws {
        let service = "com.steipete.codexbar.cache.tests.\(UUID().uuidString)"
        try KeychainCacheStore.withServiceOverrideForTesting(service) {
            KeychainCacheStore.setTestStoreForTesting(true)
            defer { KeychainCacheStore.setTestStoreForTesting(false) }

            ClaudeOAuthKeychainAccessGate.resetForTesting()
            defer { ClaudeOAuthKeychainAccessGate.resetForTesting() }

            let tempDir = FileManager.default.temporaryDirectory
                .appendingPathComponent(UUID().uuidString, isDirectory: true)
            try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true)
            let fileURL = tempDir.appendingPathComponent("credentials.json")
            try ClaudeOAuthCredentialsStore.withCredentialsURLOverrideForTesting(fileURL) {
                try ClaudeOAuthCredentialsStore.withIsolatedMemoryCacheForTesting {
                    try ClaudeOAuthCredentialsStore.withIsolatedCredentialsFileTrackingForTesting {
                        ClaudeOAuthCredentialsStore.invalidateCache()
                        ClaudeOAuthCredentialsStore._resetClaudeKeychainChangeTrackingForTesting()
                        defer {
                            ClaudeOAuthCredentialsStore.invalidateCache()
                            ClaudeOAuthCredentialsStore._resetClaudeKeychainChangeTrackingForTesting()
                        }

                        let cacheKey = ClaudeOAuthCredentialsStore.cacheKeyForTesting(
                            profileIdentifier: ClaudeOAuthCredentialsStore.credentialsProfileIdentifier(
                                environment: [:]))
                        let cachedData = self.makeCredentialsData(
                            accessToken: "cached-token",
                            expiresAt: Date(timeIntervalSinceNow: 3600))
                        KeychainCacheStore.store(
                            key: cacheKey,
                            entry: ClaudeOAuthCredentialsStore.CacheEntry(data: cachedData, storedAt: Date()))

                        let first = try ClaudeOAuthCredentialsStore.withClaudeKeychainOverridesForTesting(
                            data: cachedData,
                            fingerprint: ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprint(
                                modifiedAt: 1,
                                createdAt: 1,
                                persistentRefHash: "ref1"),
                            operation: {
                                try ClaudeOAuthCredentialsStore.load(environment: [:], allowKeychainPrompt: false)
                            })
                        #expect(first.accessToken == "cached-token")

                        ClaudeOAuthCredentialsStore._resetClaudeKeychainChangeThrottleForTesting()
                        ClaudeOAuthKeychainAccessGate.recordDenied(now: Date())

                        let keychainData = self.makeCredentialsData(
                            accessToken: "keychain-token",
                            expiresAt: Date(timeIntervalSinceNow: 3600))
                        let second = try ClaudeOAuthCredentialsStore.withClaudeKeychainOverridesForTesting(
                            data: keychainData,
                            fingerprint: ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprint(
                                modifiedAt: 2,
                                createdAt: 2,
                                persistentRefHash: "ref2"),
                            operation: {
                                try ClaudeOAuthCredentialsStore.load(
                                    environment: [:],
                                    allowKeychainPrompt: false,
                                    respectKeychainPromptCooldown: true)
                            })
                        #expect(second.accessToken == "cached-token")

                        switch KeychainCacheStore.load(key: cacheKey, as: ClaudeOAuthCredentialsStore.CacheEntry.self) {
                        case let .found(entry):
                            let parsed = try ClaudeOAuthCredentials.parse(data: entry.data)
                            #expect(parsed.accessToken == "cached-token")
                        default:
                            #expect(Bool(false))
                        }
                    }
                }
            }
        }
    }

    @Test
    func `sync from claude keychain without prompt respects backoff in background`() {
        ProviderInteractionContext.$current.withValue(.background) {
            KeychainAccessGate.withTaskOverrideForTesting(true) {
                ClaudeOAuthCredentialsStore.withKeychainAccessOverrideForTesting(true) {
                    let store = ClaudeOAuthCredentialsStore.ClaudeKeychainOverrideStore(
                        data: self.makeCredentialsData(
                            accessToken: "override-token",
                            expiresAt: Date(timeIntervalSinceNow: 3600)),
                        fingerprint: ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprint(
                            modifiedAt: 1,
                            createdAt: 1,
                            persistentRefHash: "deadbeefdead"))

                    let deniedStore = ClaudeOAuthKeychainAccessGate.DeniedUntilStore()
                    deniedStore.deniedUntil = Date(timeIntervalSinceNow: 3600)

                    ClaudeOAuthKeychainAccessGate.withDeniedUntilStoreOverrideForTesting(deniedStore) {
                        ClaudeOAuthCredentialsStore.withMutableClaudeKeychainOverrideStoreForTesting(store) {
                            #expect(ClaudeOAuthCredentialsStore
                                .syncFromClaudeKeychainWithoutPrompt(now: Date()) == false)
                        }
                    }
                }
            }
        }
    }

    @Test
    func `testing override snapshot forwards mutable Claude keychain override store across detached task`() async {
        let fingerprint = ClaudeOAuthCredentialsStore.ClaudeKeychainFingerprint(
            modifiedAt: 11,
            createdAt: 7,
            persistentRefHash: "snapshot-store")
        let store = ClaudeOAuthCredentialsStore.ClaudeKeychainOverrideStore(
            data: nil,
            fingerprint: fingerprint)

        let forwarded = await ClaudeOAuthCredentialsStore.withMutableClaudeKeychainOverrideStoreForTesting(store) {
            let snapshot = ClaudeOAuthCredentialsStore.currentTestingOverridesSnapshotForTask

            return await Task.detached {
                ClaudeOAuthKeychainPromptPreference.withTaskOverrideForTesting(.always) {
                    ClaudeOAuthCredentialsStore.withTestingOverridesSnapshotForTask(snapshot) {
                        ClaudeOAuthCredentialsStore.currentClaudeKeychainFingerprintWithoutPromptForAuthGate()
                    }
                }
            }.value
        }

        #expect(forwarded == fingerprint)
    }
}

#if os(macOS)
extension ClaudeOAuthCredentialsStoreTests {
    private func withMissingCredentialsFile<T>(operation: () throws -> T) throws -> T {
        let tempDirectory = FileManager.default.temporaryDirectory
            .appendingPathComponent(UUID().uuidString, isDirectory: true)
        try FileManager.default.createDirectory(at: tempDirectory, withIntermediateDirectories: true)
        defer { try? FileManager.default.removeItem(at: tempDirectory) }

        // Deliberately leave this URL empty: this is the missing-credentials-file bug trigger.
        let fileURL = tempDirectory.appendingPathComponent("credentials.json")
        return try ClaudeOAuthCredentialsStore.withCredentialsURLOverrideForTesting(fileURL) {
            try operation()
        }
    }

    private func withIsolatedOAuthCache<T>(operation: () throws -> T) throws -> T {
        let service = "com.steipete.codexbar.cache.tests.\(UUID().uuidString)"
        return try KeychainCacheStore.withServiceOverrideForTesting(service) {
            KeychainCacheStore.setTestStoreForTesting(true)
            defer { KeychainCacheStore.setTestStoreForTesting(false) }
            return try KeychainAccessGate.withTaskOverrideForTesting(false) {
                try ClaudeOAuthCredentialsStore.withKeychainAccessOverrideForTesting(false) {
                    try ClaudeOAuthCredentialsStore.withIsolatedMemoryCacheForTesting {
                        try ClaudeOAuthCredentialsStore.withIsolatedCredentialsFileTrackingForTesting {
                            try operation()
                        }
                    }
                }
            }
        }
    }

    @Test
    func `never mode does not repair a missing credentials file from Claude-owned Keychain`() throws {
        try self.withIsolatedOAuthCache {
            try self.withMissingCredentialsFile {
                let keychainData = self.makeCredentialsData(
                    accessToken: "test-token-placeholder",
                    expiresAt: Date(timeIntervalSinceNow: 3600))

                let error = #expect(throws: ClaudeOAuthCredentialsError.self) {
                    try ClaudeOAuthKeychainPromptPreference.withTaskOverrideForTesting(.never) {
                        try ProviderInteractionContext.$current.withValue(.background) {
                            try ClaudeOAuthCredentialsStore.withClaudeKeychainOverridesForTesting(
                                data: keychainData,
                                fingerprint: nil)
                            {
                                try ClaudeOAuthCredentialsStore.loadRecord(
                                    environment: [:],
                                    allowKeychainPrompt: false,
                                    respectKeychainPromptCooldown: false,
                                    allowClaudeKeychainRepairWithoutPrompt: true)
                            }
                        }
                    }
                }
                guard case .notFound = error else {
                    Issue.record("Expected .notFound, got \(String(describing: error))")
                    return
                }
            }
        }
    }

    @Test
    func `never mode skips all ambient Keychain readers on cache miss`() throws {
        try self.withIsolatedOAuthCache {
            try self.withMissingCredentialsFile {
                let noUIData = self.makeCredentialsData(
                    accessToken: "test-token-placeholder",
                    expiresAt: Date(timeIntervalSinceNow: 3600))
                let securityCLIData = self.makeCredentialsData(
                    accessToken: "decoy-token",
                    expiresAt: Date(timeIntervalSinceNow: 3600))
                final class ReadCounter: @unchecked Sendable {
                    var count = 0
                    var isEmpty: Bool {
                        self.count == .zero
                    }
                }
                let securityCLIReads = ReadCounter()

                let error = #expect(throws: ClaudeOAuthCredentialsError.self) {
                    try ClaudeOAuthKeychainReadStrategyPreference.withTaskOverrideForTesting(
                        .securityCLIExperimental)
                    {
                        try ClaudeOAuthKeychainPromptPreference.withTaskOverrideForTesting(.never) {
                            try ProviderInteractionContext.$current.withValue(.background) {
                                try ClaudeOAuthCredentialsStore.withSecurityCLIReadOverrideForTesting(
                                    .dynamic { _ in
                                        securityCLIReads.count += 1
                                        return securityCLIData
                                    }) {
                                        try ClaudeOAuthCredentialsStore.withClaudeKeychainOverridesForTesting(
                                            data: noUIData,
                                            fingerprint: nil)
                                        {
                                            try ClaudeOAuthCredentialsStore.loadRecord(
                                                environment: [:],
                                                allowKeychainPrompt: false,
                                                respectKeychainPromptCooldown: false,
                                                allowClaudeKeychainRepairWithoutPrompt: true)
                                        }
                                    }
                            }
                        }
                    }
                }
                guard case .notFound = error else {
                    Issue.record("Expected .notFound, got \(String(describing: error))")
                    return
                }
                #expect(securityCLIReads.isEmpty)
            }
        }
    }

    @Test
    func `never mode still blocks an interactive Keychain read even with a valid item present`() throws {
        try self.withIsolatedOAuthCache {
            try self.withMissingCredentialsFile {
                let keychainData = self.makeCredentialsData(
                    accessToken: "test-token-placeholder",
                    expiresAt: Date(timeIntervalSinceNow: 3600))

                let error = #expect(throws: ClaudeOAuthCredentialsError.self) {
                    try ClaudeOAuthKeychainPromptPreference.withTaskOverrideForTesting(.never) {
                        try ProviderInteractionContext.$current.withValue(.background) {
                            try ClaudeOAuthCredentialsStore.withClaudeKeychainOverridesForTesting(
                                data: keychainData,
                                fingerprint: nil)
                            {
                                try ClaudeOAuthCredentialsStore.load(environment: [:], allowKeychainPrompt: true)
                            }
                        }
                    }
                }
                guard case .notFound = error else {
                    Issue.record("Expected .notFound, got \(String(describing: error))")
                    return
                }
            }
        }
    }

    @Test
    func `never mode without any Keychain item still fails closed`() throws {
        try self.withIsolatedOAuthCache {
            try self.withMissingCredentialsFile {
                // A registered empty override prevents any fallback to real SecItem probes.
                let emptyKeychain = ClaudeOAuthCredentialsStore.ClaudeKeychainOverrideStore(
                    data: nil,
                    fingerprint: nil)
                let error = #expect(throws: ClaudeOAuthCredentialsError.self) {
                    try ClaudeOAuthKeychainPromptPreference.withTaskOverrideForTesting(.never) {
                        try ProviderInteractionContext.$current.withValue(.background) {
                            try ClaudeOAuthCredentialsStore
                                .withMutableClaudeKeychainOverrideStoreForTesting(emptyKeychain) {
                                    try ClaudeOAuthCredentialsStore.loadRecord(
                                        environment: [:],
                                        allowKeychainPrompt: false,
                                        respectKeychainPromptCooldown: false,
                                        allowClaudeKeychainRepairWithoutPrompt: true)
                                }
                        }
                    }
                }
                guard case .notFound = error else {
                    Issue.record("Expected .notFound, got \(String(describing: error))")
                    return
                }
            }
        }
    }

    @Test
    func `global Keychain disable blocks no-UI repair in never mode`() throws {
        try self.withIsolatedOAuthCache {
            try self.withMissingCredentialsFile {
                let keychainData = self.makeCredentialsData(
                    accessToken: "test-token-placeholder",
                    expiresAt: Date(timeIntervalSinceNow: 3600))

                let error = #expect(throws: ClaudeOAuthCredentialsError.self) {
                    try KeychainAccessGate.withTaskOverrideForTesting(true) {
                        try ClaudeOAuthCredentialsStore.withKeychainAccessOverrideForTesting(true) {
                            try ClaudeOAuthKeychainPromptPreference.withTaskOverrideForTesting(.never) {
                                try ProviderInteractionContext.$current.withValue(.background) {
                                    try ClaudeOAuthCredentialsStore.withClaudeKeychainOverridesForTesting(
                                        data: keychainData,
                                        fingerprint: nil)
                                    {
                                        try ClaudeOAuthCredentialsStore.loadRecord(
                                            environment: [:],
                                            allowKeychainPrompt: false,
                                            respectKeychainPromptCooldown: false,
                                            allowClaudeKeychainRepairWithoutPrompt: true)
                                    }
                                }
                            }
                        }
                    }
                }
                guard case .notFound = error else {
                    Issue.record("Expected .notFound, got \(String(describing: error))")
                    return
                }
            }
        }
    }
}
#endif
