import Foundation
#if canImport(SQLite3)
import SQLite3
import Testing
@testable import CodexBarCore

struct CostUsageScannerCodexPriorityTests {
    @Test
    func `parses priority turn metadata without exposing request body`() {
        let body = "INFO thread_id=11111111-1111-1111-1111-111111111111 "
            + "turn.id=22222222-2222-2222-2222-222222222222 websocket request: "
            + #"{"type":"response.create","model":"request-model","service_tier":"priority","#
            + #""instructions":"secret prompt"}"#

        let parsed = CostUsageScanner.parseCodexPriorityTraceRow(timestamp: "2026-05-10T12:00:00Z", body: body)

        #expect(parsed?.threadID == "11111111-1111-1111-1111-111111111111")
        #expect(parsed?.turnID == "22222222-2222-2222-2222-222222222222")
        #expect(parsed?.model == "request-model")
        #expect(parsed?.timestamp == "2026-05-10T12:00:00Z")
    }

    @Test
    func `parses current priority submission metadata without exposing prompt`() {
        let body = "session_loop{thread_id=thread}: Submission sub=Submission { "
            + "id: \"turn\", op: UserInput { text: \"private\" }, "
            + #"thread_settings: ThreadSettingsOverrides { service_tier: Some(Some("priority")) }"#

        let parsed = CostUsageScanner.parseCodexPriorityTraceRow(
            timestamp: "1785434553",
            body: body)

        #expect(parsed?.threadID == "thread")
        #expect(parsed?.turnID == "turn")
        #expect(parsed?.model == nil)
        #expect(parsed?.timestamp == "1785434553")
    }

    @Test
    func `ignores non priority malformed and non response request rows`() {
        let prefix = "thread_id=thread turn.id=turn websocket request: "

        #expect(CostUsageScanner.parseCodexPriorityTraceRow(
            timestamp: nil,
            body: prefix + #"{"type":"session.update","service_tier":"priority"}"#) == nil)
        #expect(CostUsageScanner.parseCodexPriorityTraceRow(
            timestamp: nil,
            body: prefix + #"{"type":"response.create"}"#) == nil)
        #expect(CostUsageScanner.parseCodexPriorityTraceRow(
            timestamp: nil,
            body: prefix + #"{"type":"response.create","service_tier":"default"}"#) == nil)
        #expect(CostUsageScanner.parseCodexPriorityTraceRow(
            timestamp: nil,
            body: prefix + #"{"#) == nil)
    }

    @Test
    func `parses completed response model without exposing response body`() {
        let body = "INFO thread_id=thread turn.id=turn websocket event: "
            + #"{"type":"response.completed","response":{"model":"completed-model","output":[{"content":"private"}]}}"#

        let parsed = CostUsageScanner.parseCodexCompletedTraceRow(body: body)

        #expect(parsed?.turnID == "turn")
        #expect(parsed?.model == "completed-model")
    }

    @Test
    func `reads priority turns from sqlite logs table`() throws {
        let env = try CostUsageTestEnvironment()
        defer { env.cleanup() }
        let dbURL = env.root.appendingPathComponent("logs_2.sqlite")
        try Self.createTestLogsDatabase(at: dbURL)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:00:00Z",
            body: "thread_id=thread-a turn.id=turn-a websocket request: "
                + #"{"type":"response.create","model":"request-model","service_tier":"priority","input":"private"}"#)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:01:00Z",
            body: """
            thread_id=thread-b turn.id=turn-b websocket request: {"type":"response.create","model":"request-model"}
            """)

        let turns = CostUsageScanner.codexPriorityTurns(databaseURL: dbURL)

        #expect(turns.keys.sorted() == ["turn-a"])
        #expect(turns["turn-a"]?.threadID == "thread-a")
        #expect(turns["turn-a"]?.model == "request-model")
    }

    @Test
    func `reads current priority submission rows from sqlite logs table`() throws {
        let env = try CostUsageTestEnvironment()
        defer { env.cleanup() }
        let dbURL = env.root.appendingPathComponent("logs_2.sqlite")
        try Self.createTestLogsDatabase(at: dbURL)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:00:00Z",
            body: "session_loop{thread_id=thread}: Submission sub=Submission { "
                + "id: \"turn\", op: UserInput { text: \"private\" }, "
                + #"thread_settings: ThreadSettingsOverrides { service_tier: Some(Some("priority")) }"#)

        let turns = CostUsageScanner.codexPriorityTurns(databaseURL: dbURL)

        #expect(turns.keys.sorted() == ["turn"])
        #expect(turns["turn"]?.threadID == "thread")
        #expect(turns["turn"]?.model == nil)
    }

    @Test
    func `cold scan uses timestamp index and warm scan uses rowid cursor`() throws {
        let env = try CostUsageTestEnvironment()
        defer { env.cleanup() }
        let dbURL = env.root.appendingPathComponent("logs_2.sqlite")
        try Self.createTestLogsDatabase(at: dbURL)

        var db: OpaquePointer?
        guard sqlite3_open_v2(dbURL.path, &db, SQLITE_OPEN_READONLY, nil) == SQLITE_OK else {
            throw SQLiteTestError.open
        }
        defer { sqlite3_close(db) }

        let coldQuery = CostUsageScanner._test_codexPriorityAccumulationQuery(
            db,
            lastRowID: 0,
            coverageSinceEpoch: 1)
        let coldPlan = try Self.queryPlan(db: db, query: coldQuery, bindings: [1])
        #expect(coldPlan.contains { $0.contains("USING INDEX idx_logs_ts") })

        let unboundedColdQuery = CostUsageScanner._test_codexPriorityAccumulationQuery(
            db,
            lastRowID: 0,
            coverageSinceEpoch: 0)
        let unboundedColdPlan = try Self.queryPlan(
            db: db,
            query: unboundedColdQuery,
            bindings: [0, 0])
        #expect(unboundedColdPlan.contains { $0.contains("USING INTEGER PRIMARY KEY") })
        #expect(!unboundedColdPlan.contains { $0.contains("USE TEMP B-TREE") })

        let warmQuery = CostUsageScanner._test_codexPriorityAccumulationQuery(
            db,
            lastRowID: 1,
            coverageSinceEpoch: 0)
        let warmPlan = try Self.queryPlan(db: db, query: warmQuery, bindings: [1, 0])
        #expect(warmPlan.contains { $0.contains("USING INTEGER PRIMARY KEY") })
    }

    @Test
    func `sqlite scan upgrades priority request alias with completed response model`() throws {
        let env = try CostUsageTestEnvironment()
        defer { env.cleanup() }
        let dbURL = env.root.appendingPathComponent("logs_2.sqlite")
        try Self.createTestLogsDatabase(at: dbURL)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:00:00Z",
            body: "thread_id=thread turn.id=turn websocket request: "
                + #"{"type":"response.create","model":"request-alias","service_tier":"priority"}"#)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:00:01Z",
            body: "thread_id=thread turn.id=turn websocket event: "
                + #"{"type":"response.completed","response":{"model":"completed-model","input":"private"}}"#)

        let turns = CostUsageScanner.codexPriorityTurns(databaseURL: dbURL)

        #expect(turns["turn"]?.model == "completed-model")
    }

    @Test
    func `sqlite scan matches spaced completed response json`() throws {
        let env = try CostUsageTestEnvironment()
        defer { env.cleanup() }
        let dbURL = env.root.appendingPathComponent("logs_2.sqlite")
        try Self.createTestLogsDatabase(at: dbURL)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:00:00Z",
            body: "thread_id=thread turn.id=turn websocket request: "
                + #"{"type":"response.create","model":"request-alias","service_tier":"priority"}"#)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:00:01Z",
            body: "thread_id=thread turn.id=turn websocket event: "
                + #"{"type": "response.completed", "response": {"model": "completed-model"}}"#)

        let turns = CostUsageScanner.codexPriorityTurns(databaseURL: dbURL)

        #expect(turns["turn"]?.model == "completed-model")
    }

    @Test
    func `sqlite scan only returns priority turns in requested day range`() throws {
        let env = try CostUsageTestEnvironment()
        defer { env.cleanup() }
        let dbURL = env.root.appendingPathComponent("logs_2.sqlite")
        try Self.createTestLogsDatabase(at: dbURL)
        let day = try env.makeLocalNoon(year: 2026, month: 5, day: 10)
        let previousDay = try #require(Calendar.current.date(byAdding: .day, value: -1, to: day))
        let dayKey = CostUsageScanner.CostUsageDayRange.dayKey(from: day)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: env.isoString(for: previousDay),
            body: "thread_id=thread-old turn.id=turn-old websocket request: "
                + #"{"type":"response.create","model":"request-model","service_tier":"priority"}"#)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: env.isoString(for: day),
            body: "thread_id=thread-new turn.id=turn-new websocket request: "
                + #"{"type":"response.create","model":"request-model","service_tier":"priority"}"#)

        let turns = CostUsageScanner.codexPriorityTurns(
            databaseURL: dbURL,
            sinceDayKey: dayKey,
            untilDayKey: dayKey)

        #expect(turns.keys.sorted() == ["turn-new"])
    }

    @Test
    func `sqlite scan uses local day boundaries for integer timestamps`() throws {
        let env = try CostUsageTestEnvironment()
        defer { env.cleanup() }
        let dbURL = env.root.appendingPathComponent("logs_2.sqlite")
        try Self.createTestLogsDatabase(at: dbURL)

        var components = DateComponents()
        components.calendar = Calendar.current
        components.year = 2026
        components.month = 5
        components.day = 10
        let dayStart = try #require(components.date)
        let dayKey = CostUsageScanner.CostUsageDayRange.dayKey(from: dayStart)
        let previousSecond = try #require(Calendar.current.date(byAdding: .second, value: -1, to: dayStart))
        let nextSecond = try #require(Calendar.current.date(byAdding: .second, value: 1, to: dayStart))

        try Self.insertTestLog(
            dbURL: dbURL,
            epochSeconds: Int64(previousSecond.timeIntervalSince1970),
            body: "thread_id=thread-before turn.id=turn-before websocket request: "
                + #"{"type":"response.create","model":"request-model","service_tier":"priority"}"#)
        try Self.insertTestLog(
            dbURL: dbURL,
            epochSeconds: Int64(nextSecond.timeIntervalSince1970),
            body: "thread_id=thread-after turn.id=turn-after websocket request: "
                + #"{"type":"response.create","model":"request-model","service_tier":"priority"}"#)

        let turns = CostUsageScanner.codexPriorityTurns(
            databaseURL: dbURL,
            sinceDayKey: dayKey,
            untilDayKey: dayKey)

        #expect(turns.keys.sorted() == ["turn-after"])
    }

    @Test
    func `incremental memo picks up rows appended after the first query`() throws {
        let env = try CostUsageTestEnvironment()
        defer { env.cleanup() }
        let dbURL = env.root.appendingPathComponent("logs_2.sqlite")
        try Self.createTestLogsDatabase(at: dbURL)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:00:00Z",
            body: "thread_id=thread-a turn.id=turn-a websocket request: "
                + #"{"type":"response.create","model":"request-model","service_tier":"priority"}"#)

        #expect(CostUsageScanner.codexPriorityTurns(databaseURL: dbURL).keys.sorted() == ["turn-a"])

        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:05:00Z",
            body: "thread_id=thread-b turn.id=turn-b websocket request: "
                + #"{"type":"response.create","model":"request-model","service_tier":"priority"}"#)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:05:01Z",
            body: "thread_id=thread-a turn.id=turn-a websocket event: "
                + #"{"type":"response.completed","response":{"model":"resolved-model"}}"#)

        let merged = CostUsageScanner.codexPriorityTurns(databaseURL: dbURL)
        #expect(merged.keys.sorted() == ["turn-a", "turn-b"])
        // A completed event appended later still upgrades the model of a turn accumulated earlier.
        #expect(merged["turn-a"]?.model == "resolved-model")
    }

    @Test
    func `memo drops pruned requests while ids keep increasing`() throws {
        let env = try CostUsageTestEnvironment()
        defer { env.cleanup() }
        let dbURL = env.root.appendingPathComponent("logs_2.sqlite")
        try Self.createTestLogsDatabase(at: dbURL)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:00:00Z",
            body: "thread_id=thread-a turn.id=turn-a websocket request: "
                + #"{"type":"response.create","model":"request-model","service_tier":"priority"}"#)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:01:00Z",
            body: "thread_id=thread-b turn.id=turn-b websocket request: "
                + #"{"type":"response.create","model":"request-model","service_tier":"priority"}"#)
        #expect(CostUsageScanner.codexPriorityTurns(databaseURL: dbURL).keys.sorted() == ["turn-a", "turn-b"])

        try Self.execDatabase(dbURL: dbURL, sql: "delete from logs where rowid = 1")
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:02:00Z",
            body: "thread_id=thread-c turn.id=turn-c websocket request: "
                + #"{"type":"response.create","model":"request-model","service_tier":"priority"}"#)

        let rebuilt = CostUsageScanner.codexPriorityTurns(databaseURL: dbURL)
        #expect(rebuilt.keys.sorted() == ["turn-b", "turn-c"])
    }

    @Test
    func `memo drops a pruned completion model without losing its request`() throws {
        let env = try CostUsageTestEnvironment()
        defer { env.cleanup() }
        let dbURL = env.root.appendingPathComponent("logs_2.sqlite")
        try Self.createTestLogsDatabase(at: dbURL)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:00:00Z",
            body: "thread_id=thread-a turn.id=turn-a websocket request: "
                + #"{"type":"response.create","model":"request-alias","service_tier":"priority"}"#)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:00:01Z",
            body: "thread_id=thread-a turn.id=turn-a websocket event: "
                + #"{"type":"response.completed","response":{"model":"resolved-model"}}"#)
        #expect(CostUsageScanner.codexPriorityTurns(databaseURL: dbURL)["turn-a"]?.model == "resolved-model")

        try Self.execDatabase(dbURL: dbURL, sql: "delete from logs where rowid = 2")
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:01:00Z",
            body: "thread_id=thread-b turn.id=turn-b websocket request: "
                + #"{"type":"response.create","model":"request-model","service_tier":"priority"}"#)

        let pruned = CostUsageScanner.codexPriorityTurns(databaseURL: dbURL)
        #expect(pruned["turn-a"]?.model == "request-alias")
        #expect(pruned["turn-b"]?.model == "request-model")
    }

    @Test
    func `memo falls back to retained duplicate request and completion rows`() throws {
        let env = try CostUsageTestEnvironment()
        defer { env.cleanup() }
        let dbURL = env.root.appendingPathComponent("logs_2.sqlite")
        try Self.createTestLogsDatabase(at: dbURL)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:00:00Z",
            body: "thread_id=thread-old turn.id=turn-a websocket request: "
                + #"{"type":"response.create","model":"request-old","service_tier":"priority"}"#)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:00:01Z",
            body: "thread_id=thread-new turn.id=turn-a websocket request: "
                + #"{"type":"response.create","model":"request-new","service_tier":"priority"}"#)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:00:02Z",
            body: "thread_id=thread-old turn.id=turn-a websocket event: "
                + #"{"type":"response.completed","response":{"model":"completed-old"}}"#)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:00:03Z",
            body: "thread_id=thread-new turn.id=turn-a websocket event: "
                + #"{"type":"response.completed","response":{"model":"completed-new"}}"#)

        let initial = CostUsageScanner.codexPriorityTurns(databaseURL: dbURL)
        #expect(initial["turn-a"]?.threadID == "thread-new")
        #expect(initial["turn-a"]?.model == "completed-new")

        try Self.execDatabase(dbURL: dbURL, sql: "delete from logs where rowid in (2, 4)")
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:01:00Z",
            body: "thread_id=thread-b turn.id=turn-b websocket request: "
                + #"{"type":"response.create","model":"request-model","service_tier":"priority"}"#)

        let pruned = CostUsageScanner.codexPriorityTurns(databaseURL: dbURL)
        #expect(pruned["turn-a"]?.threadID == "thread-old")
        #expect(pruned["turn-a"]?.model == "completed-old")
        #expect(pruned["turn-b"]?.model == "request-model")
    }

    @Test
    func `failed incremental scan does not report completion`() throws {
        let env = try CostUsageTestEnvironment()
        defer { env.cleanup() }
        let dbURL = env.root.appendingPathComponent("logs_2.sqlite")
        try Self.createTestLogsDatabase(at: dbURL)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:00:00Z",
            body: "thread_id=thread-a turn.id=turn-a websocket request: "
                + #"{"type":"response.create","model":"request-model","service_tier":"priority"}"#)

        var db: OpaquePointer?
        guard sqlite3_open_v2(dbURL.path, &db, SQLITE_OPEN_READONLY, nil) == SQLITE_OK else {
            throw SQLiteTestError.open
        }
        defer { sqlite3_close(db) }
        sqlite3_progress_handler(db, 1, { _ in 1 }, nil)

        var state = CostUsageScanner.CodexPriorityTurnsMemoState(
            observationID: 1,
            coverageSinceEpoch: 0,
            lastRowID: 0,
            fileIdentity: nil,
            turns: [:],
            requestSourcesByTurnID: [:],
            priorityCompletedModelsByTurnID: [:],
            completedModelsByTurnID: [:],
            completedTurnIDInsertionOrder: [],
            completedTurnIDInsertionOrderStartIndex: 0)

        #expect(!CostUsageScanner._test_accumulateCodexPriorityTurns(db, into: &state))
    }

    @Test
    func `memo rescans when requested window expands earlier than accumulated coverage`() throws {
        let env = try CostUsageTestEnvironment()
        defer { env.cleanup() }
        let dbURL = env.root.appendingPathComponent("logs_2.sqlite")
        try Self.createTestLogsDatabase(at: dbURL)
        // Live refreshes always query through today, which is the memoized path.
        let today = Date()
        let yesterday = try #require(Calendar.current.date(byAdding: .day, value: -1, to: today))
        let todayKey = CostUsageScanner.CostUsageDayRange.dayKey(from: today)
        let yesterdayKey = CostUsageScanner.CostUsageDayRange.dayKey(from: yesterday)
        let formatter = ISO8601DateFormatter()
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: formatter.string(from: yesterday),
            body: "thread_id=thread-old turn.id=turn-old websocket request: "
                + #"{"type":"response.create","model":"request-model","service_tier":"priority"}"#)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: formatter.string(from: today),
            body: "thread_id=thread-new turn.id=turn-new websocket request: "
                + #"{"type":"response.create","model":"request-model","service_tier":"priority"}"#)

        let narrow = CostUsageScanner.codexPriorityTurns(
            databaseURL: dbURL,
            sinceDayKey: todayKey,
            untilDayKey: todayKey)
        #expect(narrow.keys.sorted() == ["turn-new"])

        let expanded = CostUsageScanner.codexPriorityTurns(
            databaseURL: dbURL,
            sinceDayKey: yesterdayKey,
            untilDayKey: todayKey)
        #expect(expanded.keys.sorted() == ["turn-new", "turn-old"])
    }

    @Test
    func `memo rescans when the database shrinks or is replaced`() throws {
        let env = try CostUsageTestEnvironment()
        defer { env.cleanup() }
        let dbURL = env.root.appendingPathComponent("logs_2.sqlite")
        try Self.createTestLogsDatabase(at: dbURL)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:00:00Z",
            body: "thread_id=thread-a turn.id=turn-a websocket request: "
                + #"{"type":"response.create","model":"request-model","service_tier":"priority"}"#)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:01:00Z",
            body: "thread_id=thread-b turn.id=turn-b websocket request: "
                + #"{"type":"response.create","model":"request-model","service_tier":"priority"}"#)
        #expect(CostUsageScanner.codexPriorityTurns(databaseURL: dbURL).count == 2)

        try FileManager.default.removeItem(at: dbURL)
        try Self.createTestLogsDatabase(at: dbURL)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-11T09:00:00Z",
            body: "thread_id=thread-c turn.id=turn-c websocket request: "
                + #"{"type":"response.create","model":"request-model","service_tier":"priority"}"#)

        let replaced = CostUsageScanner.codexPriorityTurns(databaseURL: dbURL)
        #expect(replaced.keys.sorted() == ["turn-c"])
    }

    @Test
    func `database replacement during open is rejected`() throws {
        let env = try CostUsageTestEnvironment()
        defer { env.cleanup() }
        let dbURL = env.root.appendingPathComponent("logs_2.sqlite")
        let oldURL = env.root.appendingPathComponent("logs-old.sqlite")
        try Self.createTestLogsDatabase(at: dbURL)
        var replacementError: Error?

        let opened = CostUsageScanner.openCodexPriorityDatabase(at: dbURL) {
            do {
                try FileManager.default.moveItem(at: dbURL, to: oldURL)
                try Self.createTestLogsDatabase(at: dbURL)
            } catch {
                replacementError = error
            }
        }
        if let opened {
            sqlite3_close(opened.db)
        }

        #expect(replacementError == nil)
        #expect(opened == nil)
    }

    @Test
    func `overlapping refresh writeback cannot replace newer memo state`() throws {
        let env = try CostUsageTestEnvironment()
        defer { env.cleanup() }
        let dbURL = env.root.appendingPathComponent("logs_2.sqlite")
        try Self.createTestLogsDatabase(at: dbURL)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:00:00Z",
            body: "thread_id=thread-a turn.id=turn-a websocket request: "
                + #"{"type":"response.create","model":"request-model","service_tier":"priority"}"#)
        try Self.insertTestLog(
            dbURL: dbURL,
            timestamp: "2026-05-10T12:01:00Z",
            body: "thread_id=thread-b turn.id=turn-b websocket request: "
                + #"{"type":"response.create","model":"request-model","service_tier":"priority"}"#)
        #expect(CostUsageScanner.codexPriorityTurns(databaseURL: dbURL).count == 2)
        let stored = try #require(CostUsageScanner._test_codexPriorityTurnsMemoState(forPath: dbURL.path))

        // A slower overlapping refresh writes back a snapshot read before the second row was
        // appended: an older cursor that only observed the first turn. It must not win.
        var stale = stored
        stale.lastRowID -= 1
        stale.turns = stored.turns.filter { $0.key == "turn-a" }
        CostUsageScanner.storeCodexPriorityTurnsMemoIfNewer(stale, forPath: dbURL.path)

        let retained = try #require(CostUsageScanner._test_codexPriorityTurnsMemoState(forPath: dbURL.path))
        #expect(retained.lastRowID == stored.lastRowID)
        #expect(retained.turns.keys.sorted() == ["turn-a", "turn-b"])

        // A snapshot with a newer cursor still replaces the stored state.
        var newer = stored
        newer.lastRowID += 1
        CostUsageScanner.storeCodexPriorityTurnsMemoIfNewer(newer, forPath: dbURL.path)
        #expect(
            CostUsageScanner._test_codexPriorityTurnsMemoState(forPath: dbURL.path)?
                .lastRowID == stored.lastRowID + 1)

        // A full rescan that expanded coverage earlier than the stored window also replaces,
        // even when its cursor is not ahead, so broader history is never discarded.
        var broader = stored
        broader.coverageSinceEpoch -= 1
        CostUsageScanner.storeCodexPriorityTurnsMemoIfNewer(broader, forPath: dbURL.path)
        #expect(
            CostUsageScanner._test_codexPriorityTurnsMemoState(forPath: dbURL.path)?
                .coverageSinceEpoch == broader.coverageSinceEpoch)
    }

    @Test
    func `memo bounds retained completion metadata for non-priority turns`() throws {
        let env = try CostUsageTestEnvironment()
        defer { env.cleanup() }
        let dbURL = env.root.appendingPathComponent("logs_2.sqlite")
        try Self.createTestLogsDatabase(at: dbURL)
        let limit = CostUsageScanner.codexPriorityCompletedModelRetentionLimit
        let overflow = limit + 8
        let epoch = Self.epochSeconds("2026-05-10T12:00:00Z")

        // A known priority turn keeps its resolved completion outside the bounded pending
        // cache while thousands of unrelated completions flow through the process.
        var rows = [
            (
                epochSeconds: epoch,
                body: "thread_id=priority turn.id=priority websocket request: "
                    + #"{"type":"response.create","model":"priority-alias","service_tier":"priority"}"#),
            (
                epochSeconds: epoch,
                body: "thread_id=priority turn.id=priority websocket event: "
                    + #"{"type":"response.completed","response":{"model":"resolved-model"}}"#),
        ]
        rows.append(contentsOf: (0..<(limit + overflow)).map { index in
            (
                epochSeconds: epoch,
                body: "thread_id=thread-\(index) turn.id=turn-\(index) websocket event: "
                    + #"{"type":"response.completed","response":{"model":"completed-model"}}"#)
        })
        rows.append((
            epochSeconds: epoch,
            body: "thread_id=thread-0 turn.id=turn-0 websocket request: "
                + #"{"type":"response.create","model":"alias-evicted","service_tier":"priority"}"#))
        let newest = limit + overflow - 1
        rows.append((
            epochSeconds: epoch,
            body: "thread_id=thread-\(newest) turn.id=turn-\(newest) "
                + "websocket request: "
                + #"{"type":"response.create","model":"alias-retained","service_tier":"priority"}"#))
        try Self.insertTestLogs(dbURL: dbURL, rows: rows)

        let turns = CostUsageScanner.codexPriorityTurns(databaseURL: dbURL)

        let memo = try #require(CostUsageScanner._test_codexPriorityTurnsMemoState(forPath: dbURL.path))
        #expect(memo.completedModelsByTurnID.count == limit - 1)
        #expect(
            memo.completedTurnIDInsertionOrder.count
                - memo.completedTurnIDInsertionOrderStartIndex == limit - 1)
        #expect(memo.completedTurnIDInsertionOrder.count < limit * 2)
        #expect(memo.priorityCompletedModelsByTurnID.count == 2)
        // The oldest completions were evicted, so the early request keeps its alias; the
        // recent completion is still retained and upgrades its request.
        #expect(turns["priority"]?.model == "resolved-model")
        #expect(turns["turn-0"]?.model == "alias-evicted")
        #expect(turns["turn-\(newest)"]?.model == "completed-model")
    }

    static func insertTestLogs(dbURL: URL, rows: [(epochSeconds: Int64, body: String)]) throws {
        var db: OpaquePointer?
        guard sqlite3_open(dbURL.path, &db) == SQLITE_OK else { throw SQLiteTestError.open }
        defer { sqlite3_close(db) }

        var stmt: OpaquePointer?
        guard sqlite3_prepare_v2(db, "insert into logs (ts, feedback_log_body) values (?, ?)", -1, &stmt, nil)
            == SQLITE_OK
        else { throw SQLiteTestError.prepare }
        defer { sqlite3_finalize(stmt) }

        try self.exec(db, "begin transaction")
        let transient = unsafeBitCast(-1, to: sqlite3_destructor_type.self)
        for row in rows {
            sqlite3_bind_int64(stmt, 1, row.epochSeconds)
            sqlite3_bind_text(stmt, 2, row.body, -1, transient)
            guard sqlite3_step(stmt) == SQLITE_DONE else { throw SQLiteTestError.step }
            sqlite3_reset(stmt)
        }
        try self.exec(db, "commit")
    }

    static func createTestLogsDatabase(at dbURL: URL) throws {
        var db: OpaquePointer?
        guard sqlite3_open(dbURL.path, &db) == SQLITE_OK else { throw SQLiteTestError.open }
        defer { sqlite3_close(db) }
        try self.exec(
            db,
            "create table logs (id integer primary key autoincrement, ts integer not null, feedback_log_body text)")
        try self.exec(db, "create index idx_logs_ts on logs(ts desc, id desc)")
    }

    static func queryPlan(
        db: OpaquePointer?,
        query: String,
        bindings: [Int64]) throws -> [String]
    {
        var stmt: OpaquePointer?
        guard sqlite3_prepare_v2(db, "explain query plan \(query)", -1, &stmt, nil) == SQLITE_OK else {
            throw SQLiteTestError.prepare
        }
        defer { sqlite3_finalize(stmt) }
        for (offset, value) in bindings.enumerated() {
            sqlite3_bind_int64(stmt, Int32(offset + 1), value)
        }

        var details: [String] = []
        while sqlite3_step(stmt) == SQLITE_ROW {
            if let detail = sqlite3_column_text(stmt, 3) {
                details.append(String(cString: detail))
            }
        }
        return details
    }

    static func insertTestLog(dbURL: URL, timestamp: String, body: String) throws {
        try self.insertTestLog(dbURL: dbURL, epochSeconds: self.epochSeconds(timestamp), body: body)
    }

    static func insertTestLog(dbURL: URL, epochSeconds: Int64, body: String) throws {
        var db: OpaquePointer?
        guard sqlite3_open(dbURL.path, &db) == SQLITE_OK else { throw SQLiteTestError.open }
        defer { sqlite3_close(db) }

        var stmt: OpaquePointer?
        guard sqlite3_prepare_v2(db, "insert into logs (ts, feedback_log_body) values (?, ?)", -1, &stmt, nil)
            == SQLITE_OK
        else { throw SQLiteTestError.prepare }
        defer { sqlite3_finalize(stmt) }

        let transient = unsafeBitCast(-1, to: sqlite3_destructor_type.self)
        sqlite3_bind_int64(stmt, 1, epochSeconds)
        sqlite3_bind_text(stmt, 2, body, -1, transient)
        guard sqlite3_step(stmt) == SQLITE_DONE else { throw SQLiteTestError.step }
    }

    private static func execDatabase(dbURL: URL, sql: String) throws {
        var db: OpaquePointer?
        guard sqlite3_open(dbURL.path, &db) == SQLITE_OK else { throw SQLiteTestError.open }
        defer { sqlite3_close(db) }
        try self.exec(db, sql)
    }

    private static func epochSeconds(_ timestamp: String) -> Int64 {
        let formatter = ISO8601DateFormatter()
        formatter.formatOptions = [.withInternetDateTime]
        guard let date = formatter.date(from: timestamp) else { return 0 }
        return Int64(date.timeIntervalSince1970)
    }

    private static func exec(_ db: OpaquePointer?, _ sql: String) throws {
        var message: UnsafeMutablePointer<CChar>?
        guard sqlite3_exec(db, sql, nil, nil, &message) == SQLITE_OK else {
            sqlite3_free(message)
            throw SQLiteTestError.exec
        }
    }

    private enum SQLiteTestError: Error {
        case open
        case prepare
        case step
        case exec
    }
}
#endif
