import CodexBarCore
import Foundation
import Testing
@testable import CodexBar

@Suite(.serialized)
struct HistoricalUsagePaceTests {
    @Test
    func `history store reconstructs deterministic monotone curve`() async throws {
        let fileURL = Self.makeTempURL()
        let store = HistoricalUsageHistoryStore(fileURL: fileURL)
        let windowMinutes = 10080
        let duration = TimeInterval(windowMinutes) * 60
        let resetsAt = Date().addingTimeInterval(-24 * 60 * 60)
        let windowStart = resetsAt.addingTimeInterval(-duration)

        let samples: [(u: Double, used: Double)] = [
            (0.02, 3),
            (0.10, 10),
            (0.40, 40),
            (0.60, 60),
            (0.80, 80),
            (0.98, 95),
        ]
        for sample in samples {
            let sampledAt = windowStart.addingTimeInterval(sample.u * duration)
            _ = await store.recordCodexWeekly(
                window: RateWindow(
                    usedPercent: sample.used,
                    windowMinutes: windowMinutes,
                    resetsAt: resetsAt,
                    resetDescription: nil),
                sampledAt: sampledAt,
                accountKey: nil)
        }

        let dataset = await store.loadCodexDataset(accountKey: nil)
        #expect(dataset?.weeks.count == 1)
        let curve = try #require(dataset?.weeks.first?.curve)
        #expect(curve.count == CodexHistoricalDataset.gridPointCount)
        #expect(abs(curve[0]) < 0.001)
        for index in 1..<curve.count {
            #expect(curve[index] >= curve[index - 1])
        }
        // u=0.5 is index 84 in a 169-point grid.
        #expect(abs(curve[84] - 50) < 0.5)
    }

    @Test
    func `reconstruct week curve anchors at zero at window start`() async throws {
        let fileURL = Self.makeTempURL()
        let store = HistoricalUsageHistoryStore(fileURL: fileURL)
        let windowMinutes = 10080
        let duration = TimeInterval(windowMinutes) * 60
        let resetsAt = Date().addingTimeInterval(-24 * 60 * 60)
        let windowStart = resetsAt.addingTimeInterval(-duration)

        let samples: [(u: Double, used: Double)] = [
            (0.10, 12),
            (0.25, 25),
            (0.50, 50),
            (0.70, 70),
            (0.90, 90),
            (0.98, 96),
        ]
        for sample in samples {
            _ = await store.recordCodexWeekly(
                window: RateWindow(
                    usedPercent: sample.used,
                    windowMinutes: windowMinutes,
                    resetsAt: resetsAt,
                    resetDescription: nil),
                sampledAt: windowStart.addingTimeInterval(sample.u * duration),
                accountKey: nil)
        }

        let curve = try #require(await store.loadCodexDataset(accountKey: nil)?.weeks.first?.curve)
        #expect(abs(curve[0]) < 0.001)
        #expect(curve[1] >= curve[0])
    }

    @Test
    func `reconstruct week curve adds end anchor without breaking monotonicity`() async throws {
        let fileURL = Self.makeTempURL()
        let store = HistoricalUsageHistoryStore(fileURL: fileURL)
        let windowMinutes = 10080
        let duration = TimeInterval(windowMinutes) * 60
        let resetsAt = Date().addingTimeInterval(-24 * 60 * 60)
        let windowStart = resetsAt.addingTimeInterval(-duration)

        let samples: [(u: Double, used: Double)] = [
            (0.02, 2),
            (0.15, 18),
            (0.35, 40),
            (0.55, 58),
            (0.80, 82),
            (0.90, 88),
        ]
        for sample in samples {
            _ = await store.recordCodexWeekly(
                window: RateWindow(
                    usedPercent: sample.used,
                    windowMinutes: windowMinutes,
                    resetsAt: resetsAt,
                    resetDescription: nil),
                sampledAt: windowStart.addingTimeInterval(sample.u * duration),
                accountKey: nil)
        }

        let curve = try #require(await store.loadCodexDataset(accountKey: nil)?.weeks.first?.curve)
        for index in 1..<curve.count {
            #expect(curve[index] >= curve[index - 1])
        }
        let last = try #require(curve.last)
        #expect(abs(last - 88) < 1.5)
    }

    @Test
    func `history store requires start and end coverage for complete week`() async {
        let fileURL = Self.makeTempURL()
        let store = HistoricalUsageHistoryStore(fileURL: fileURL)
        let windowMinutes = 10080
        let duration = TimeInterval(windowMinutes) * 60
        let resetsAt = Date().addingTimeInterval(-24 * 60 * 60)
        let windowStart = resetsAt.addingTimeInterval(-duration)

        // Missing first-24h coverage on purpose.
        let lateOnlySamples: [(u: Double, used: Double)] = [
            (0.30, 20),
            (0.45, 35),
            (0.60, 50),
            (0.75, 65),
            (0.90, 80),
            (0.98, 92),
        ]
        for sample in lateOnlySamples {
            let sampledAt = windowStart.addingTimeInterval(sample.u * duration)
            _ = await store.recordCodexWeekly(
                window: RateWindow(
                    usedPercent: sample.used,
                    windowMinutes: windowMinutes,
                    resetsAt: resetsAt,
                    resetDescription: nil),
                sampledAt: sampledAt,
                accountKey: nil)
        }

        #expect(await store.loadCodexDataset(accountKey: nil) == nil)
    }

    @Test
    func `evaluator applies smoothed probability and hides risk below threshold`() throws {
        let now = Date(timeIntervalSince1970: 0)
        let windowMinutes = 10080
        let duration = TimeInterval(windowMinutes) * 60
        let currentResetsAt = now.addingTimeInterval(duration / 2)
        let window = RateWindow(
            usedPercent: 50,
            windowMinutes: windowMinutes,
            resetsAt: currentResetsAt,
            resetDescription: nil)

        let fiveTrueWeeks = (0..<5).map { index in
            HistoricalWeekProfile(
                resetsAt: currentResetsAt.addingTimeInterval(-duration * Double(index + 1)),
                windowMinutes: windowMinutes,
                curve: Self.linearCurve(end: 100))
        }
        let paceAllTrue = CodexHistoricalPaceEvaluator.evaluate(
            window: window,
            now: now,
            dataset: CodexHistoricalDataset(weeks: fiveTrueWeeks))
        let probabilityTrue = try #require(paceAllTrue?.runOutProbability)
        #expect(probabilityTrue > 0)
        #expect(probabilityTrue < 1)

        let fiveFalseWeeks = (0..<5).map { index in
            HistoricalWeekProfile(
                resetsAt: currentResetsAt.addingTimeInterval(-duration * Double(index + 1)),
                windowMinutes: windowMinutes,
                curve: Self.linearCurve(end: 80))
        }
        let paceAllFalse = CodexHistoricalPaceEvaluator.evaluate(
            window: window,
            now: now,
            dataset: CodexHistoricalDataset(weeks: fiveFalseWeeks))
        let probabilityFalse = try #require(paceAllFalse?.runOutProbability)
        #expect(probabilityFalse > 0)
        #expect(probabilityFalse < 1)

        let fourWeeks = Array(fiveTrueWeeks.prefix(4))
        let paceFourWeeks = CodexHistoricalPaceEvaluator.evaluate(
            window: window,
            now: now,
            dataset: CodexHistoricalDataset(weeks: fourWeeks))
        #expect(paceFourWeeks?.runOutProbability == nil)
    }

    @Test
    func `evaluator never returns negative eta with outlier week`() {
        let now = Date(timeIntervalSince1970: 0)
        let windowMinutes = 10080
        let duration = TimeInterval(windowMinutes) * 60
        let currentResetsAt = now.addingTimeInterval(duration / 2)
        let window = RateWindow(
            usedPercent: 50,
            windowMinutes: windowMinutes,
            resetsAt: currentResetsAt,
            resetDescription: nil)

        var weeks = (0..<4).map { index in
            HistoricalWeekProfile(
                resetsAt: currentResetsAt.addingTimeInterval(-duration * Double(index + 1)),
                windowMinutes: windowMinutes,
                curve: Self.linearCurve(end: 100))
        }
        weeks.append(HistoricalWeekProfile(
            resetsAt: currentResetsAt.addingTimeInterval(-duration * 5),
            windowMinutes: windowMinutes,
            curve: Self.outlierCurve()))

        let pace = CodexHistoricalPaceEvaluator.evaluate(
            window: window,
            now: now,
            dataset: CodexHistoricalDataset(weeks: weeks))

        #expect(pace != nil)
        #expect((pace?.etaSeconds ?? 0) >= 0)
    }

    @Test
    func `history store backfills from usage breakdown when history is empty`() async {
        let fileURL = Self.makeTempURL()
        let store = HistoricalUsageHistoryStore(fileURL: fileURL)
        let now = Date(timeIntervalSince1970: 1_770_000_000)
        let windowMinutes = 10080
        let resetsAt = now.addingTimeInterval(2 * 24 * 60 * 60)
        let referenceWindow = RateWindow(
            usedPercent: 50,
            windowMinutes: windowMinutes,
            resetsAt: resetsAt,
            resetDescription: nil)

        let breakdown = Self.syntheticBreakdown(endingAt: now, days: 35, dailyCredits: 10)
        let dataset = await store.backfillCodexWeeklyFromUsageBreakdown(
            breakdown,
            referenceWindow: referenceWindow,
            now: now,
            accountKey: nil)

        #expect((dataset?.weeks.count ?? 0) >= 3)
    }

    @Test
    func `history store backfill is idempotent for existing weeks`() async {
        let fileURL = Self.makeTempURL()
        let store = HistoricalUsageHistoryStore(fileURL: fileURL)
        let now = Date(timeIntervalSince1970: 1_770_000_000)
        let windowMinutes = 10080
        let resetsAt = now.addingTimeInterval(2 * 24 * 60 * 60)
        let referenceWindow = RateWindow(
            usedPercent: 50,
            windowMinutes: windowMinutes,
            resetsAt: resetsAt,
            resetDescription: nil)

        let breakdown = Self.syntheticBreakdown(endingAt: now, days: 35, dailyCredits: 10)
        let first = await store.backfillCodexWeeklyFromUsageBreakdown(
            breakdown,
            referenceWindow: referenceWindow,
            now: now,
            accountKey: nil)
        let recordsAfterFirst = (try? Self.readHistoricalRecords(from: fileURL)) ?? []
        let second = await store.backfillCodexWeeklyFromUsageBreakdown(
            breakdown,
            referenceWindow: referenceWindow,
            now: now,
            accountKey: nil)
        let recordsAfterSecond = (try? Self.readHistoricalRecords(from: fileURL)) ?? []

        #expect((first?.weeks.count ?? 0) >= 3)
        #expect(first?.weeks.count == second?.weeks.count)
        #expect(recordsAfterSecond.count == recordsAfterFirst.count)
        #expect(Self.recordDedupKeyCount(recordsAfterSecond) == recordsAfterSecond.count)
        #expect(Self.datasetCurveSignature(first) == Self.datasetCurveSignature(second))
    }

    @Test
    func `history store backfill is idempotent across minute scale reset jitter`() async {
        let fileURL = Self.makeTempURL()
        let store = HistoricalUsageHistoryStore(fileURL: fileURL)
        let now = Date(timeIntervalSince1970: 1_770_000_000)
        let windowMinutes = 10080
        let canonicalReset = Self.normalizeReset(now.addingTimeInterval(2 * 24 * 60 * 60))
        let firstWindow = RateWindow(
            usedPercent: 50,
            windowMinutes: windowMinutes,
            resetsAt: canonicalReset.addingTimeInterval(-90),
            resetDescription: nil)
        let secondWindow = RateWindow(
            usedPercent: 50,
            windowMinutes: windowMinutes,
            resetsAt: canonicalReset.addingTimeInterval(90),
            resetDescription: nil)

        let breakdown = Self.syntheticBreakdown(endingAt: now, days: 35, dailyCredits: 10)
        let first = await store.backfillCodexWeeklyFromUsageBreakdown(
            breakdown,
            referenceWindow: firstWindow,
            now: now,
            accountKey: nil)
        let recordsAfterFirst = (try? Self.readHistoricalRecords(from: fileURL)) ?? []
        let second = await store.backfillCodexWeeklyFromUsageBreakdown(
            breakdown,
            referenceWindow: secondWindow,
            now: now,
            accountKey: nil)
        let recordsAfterSecond = (try? Self.readHistoricalRecords(from: fileURL)) ?? []

        #expect((first?.weeks.count ?? 0) >= 3)
        #expect(first?.weeks.count == second?.weeks.count)
        #expect(recordsAfterSecond.count == recordsAfterFirst.count)
        #expect(Self.datasetCurveSignature(first) == Self.datasetCurveSignature(second))
    }

    @Test
    func `history store backfill fills incomplete existing week`() async {
        let fileURL = Self.makeTempURL()
        let store = HistoricalUsageHistoryStore(fileURL: fileURL)
        let now = Date(timeIntervalSince1970: 1_770_000_000)
        let windowMinutes = 10080
        let duration = TimeInterval(windowMinutes) * 60
        let resetsAt = now.addingTimeInterval(2 * 24 * 60 * 60)
        let referenceWindow = RateWindow(
            usedPercent: 50,
            windowMinutes: windowMinutes,
            resetsAt: resetsAt,
            resetDescription: nil)

        let incompleteReset = resetsAt.addingTimeInterval(-2 * duration)
        let incompleteStart = incompleteReset.addingTimeInterval(-duration)
        _ = await store.recordCodexWeekly(
            window: RateWindow(
                usedPercent: 42,
                windowMinutes: windowMinutes,
                resetsAt: incompleteReset,
                resetDescription: nil),
            sampledAt: incompleteStart.addingTimeInterval(duration * 0.5),
            accountKey: nil)

        let breakdown = Self.syntheticBreakdown(endingAt: now, days: 29, dailyCredits: 10)
        let dataset = await store.backfillCodexWeeklyFromUsageBreakdown(
            breakdown,
            referenceWindow: referenceWindow,
            now: now,
            accountKey: nil)

        #expect((dataset?.weeks.count ?? 0) >= 3)
    }

    @Test
    func `history store should accept does not cross window minutes regimes`() async throws {
        let fileURL = Self.makeTempURL()
        let store = HistoricalUsageHistoryStore(fileURL: fileURL)
        let sampledAt = Date(timeIntervalSince1970: 1_770_000_000)
        let resetsAt = sampledAt.addingTimeInterval(3 * 24 * 60 * 60)

        _ = await store.recordCodexWeekly(
            window: RateWindow(
                usedPercent: 20,
                windowMinutes: 10080,
                resetsAt: resetsAt,
                resetDescription: nil),
            sampledAt: sampledAt,
            accountKey: nil)
        _ = await store.recordCodexWeekly(
            window: RateWindow(
                usedPercent: 20,
                windowMinutes: 20160,
                resetsAt: resetsAt,
                resetDescription: nil),
            sampledAt: sampledAt.addingTimeInterval(60),
            accountKey: nil)

        let data = try Data(contentsOf: fileURL)
        let text = String(data: data, encoding: .utf8) ?? ""
        let lines = text
            .split(separator: "\n", omittingEmptySubsequences: true)
            .map(String.init)
        #expect(lines.count == 2)
    }

    @Test
    func `weeks with reset jitter are grouped together`() async {
        let fileURL = Self.makeTempURL()
        let store = HistoricalUsageHistoryStore(fileURL: fileURL)
        let windowMinutes = 10080
        let duration = TimeInterval(windowMinutes) * 60
        let canonicalReset = Self.normalizeReset(Date(timeIntervalSince1970: 1_770_000_000))
        let windowStart = canonicalReset.addingTimeInterval(-duration)

        let samples: [(u: Double, used: Double)] = [
            (0.02, 2),
            (0.10, 10),
            (0.30, 30),
            (0.50, 50),
            (0.80, 80),
            (0.98, 95),
        ]
        for (index, sample) in samples.enumerated() {
            let jitteredReset = canonicalReset.addingTimeInterval(index.isMultiple(of: 2) ? -100 : 100)
            _ = await store.recordCodexWeekly(
                window: RateWindow(
                    usedPercent: sample.used,
                    windowMinutes: windowMinutes,
                    resetsAt: jitteredReset,
                    resetDescription: nil),
                sampledAt: windowStart.addingTimeInterval(sample.u * duration),
                accountKey: nil)
        }

        let dataset = await store.loadCodexDataset(accountKey: nil)
        #expect(dataset?.weeks.count == 1)
    }

    @Test
    func `backfill matches incomplete week when reset jitter exists`() async throws {
        let fileURL = Self.makeTempURL()
        let store = HistoricalUsageHistoryStore(fileURL: fileURL)
        let now = Date(timeIntervalSince1970: 1_770_000_000)
        let windowMinutes = 10080
        let duration = TimeInterval(windowMinutes) * 60
        let currentReset = now.addingTimeInterval(2 * 24 * 60 * 60)
        let targetReset = currentReset.addingTimeInterval(-2 * duration)
        let targetStart = targetReset.addingTimeInterval(-duration)

        _ = await store.recordCodexWeekly(
            window: RateWindow(
                usedPercent: 35,
                windowMinutes: windowMinutes,
                resetsAt: targetReset.addingTimeInterval(120),
                resetDescription: nil),
            sampledAt: targetStart.addingTimeInterval(duration * 0.5),
            accountKey: nil)

        let datasetBefore = await store.loadCodexDataset(accountKey: nil)
        #expect(datasetBefore == nil)

        let referenceWindow = RateWindow(
            usedPercent: 50,
            windowMinutes: windowMinutes,
            resetsAt: currentReset,
            resetDescription: nil)
        let breakdown = Self.syntheticBreakdown(endingAt: now, days: 29, dailyCredits: 10)
        let datasetAfter = await store.backfillCodexWeeklyFromUsageBreakdown(
            breakdown,
            referenceWindow: referenceWindow,
            now: now,
            accountKey: nil)
        #expect((datasetAfter?.weeks.count ?? 0) >= 3)

        let normalizedTargetReset = Self.normalizeReset(targetReset)
        let records = try Self.readHistoricalRecords(from: fileURL)
        let matching = records.filter { $0.accountKey == nil && $0.resetsAt == normalizedTargetReset }
        #expect(matching.count > 1)
    }

    @Test
    func `backfill does not stop at three weeks when more backfillable weeks exist`() async throws {
        let fileURL = Self.makeTempURL()
        let store = HistoricalUsageHistoryStore(fileURL: fileURL)
        let now = Date(timeIntervalSince1970: 1_770_000_000)
        let windowMinutes = 10080
        let duration = TimeInterval(windowMinutes) * 60
        let currentReset = now.addingTimeInterval(2 * 24 * 60 * 60)

        // Seed 3 complete weeks.
        for weekOffset in 1...3 {
            let reset = currentReset.addingTimeInterval(-duration * Double(weekOffset))
            let start = reset.addingTimeInterval(-duration)
            let samples: [(u: Double, used: Double)] = [
                (0.02, 2), (0.10, 10), (0.30, 30), (0.50, 50), (0.80, 80), (0.98, 95),
            ]
            for sample in samples {
                _ = await store.recordCodexWeekly(
                    window: RateWindow(
                        usedPercent: sample.used,
                        windowMinutes: windowMinutes,
                        resetsAt: reset,
                        resetDescription: nil),
                    sampledAt: start.addingTimeInterval(sample.u * duration),
                    accountKey: nil)
            }
        }

        let pre = try #require(await store.loadCodexDataset(accountKey: nil))
        #expect(pre.weeks.count == 3)

        let referenceWindow = RateWindow(
            usedPercent: 50,
            windowMinutes: windowMinutes,
            resetsAt: currentReset,
            resetDescription: nil)
        let breakdown = Self.syntheticBreakdown(endingAt: now, days: 56, dailyCredits: 10)
        let post = await store.backfillCodexWeeklyFromUsageBreakdown(
            breakdown,
            referenceWindow: referenceWindow,
            now: now,
            accountKey: nil)

        #expect((post?.weeks.count ?? 0) > 3)
    }

    @Test
    func `load dataset uses only current account key`() async throws {
        let fileURL = Self.makeTempURL()
        let store = HistoricalUsageHistoryStore(fileURL: fileURL)
        let windowMinutes = 10080
        let duration = TimeInterval(windowMinutes) * 60
        let reset = Date(timeIntervalSince1970: 1_770_000_000)
        let start = reset.addingTimeInterval(-duration)
        let samples: [Double] = [0.02, 0.10, 0.30, 0.50, 0.80, 0.98]

        for u in samples {
            _ = await store.recordCodexWeekly(
                window: RateWindow(
                    usedPercent: u * 100,
                    windowMinutes: windowMinutes,
                    resetsAt: reset,
                    resetDescription: nil),
                sampledAt: start.addingTimeInterval(u * duration),
                accountKey: "acct-a")
        }
        for u in samples {
            _ = await store.recordCodexWeekly(
                window: RateWindow(
                    usedPercent: min(100, (u * 100) + 10),
                    windowMinutes: windowMinutes,
                    resetsAt: reset,
                    resetDescription: nil),
                sampledAt: start.addingTimeInterval(u * duration),
                accountKey: "acct-b")
        }

        let aDataset = try #require(await store.loadCodexDataset(accountKey: "acct-a"))
        let bDataset = try #require(await store.loadCodexDataset(accountKey: "acct-b"))
        let nilDataset = await store.loadCodexDataset(accountKey: nil)
        #expect(aDataset.weeks.count == 1)
        #expect(bDataset.weeks.count == 1)
        #expect(nilDataset == nil)
        #expect(abs(aDataset.weeks[0].curve[84] - bDataset.weeks[0].curve[84]) > 0.1)
    }

    @Test
    func `backfill filters by account key`() async throws {
        let fileURL = Self.makeTempURL()
        let store = HistoricalUsageHistoryStore(fileURL: fileURL)
        let now = Date(timeIntervalSince1970: 1_770_000_000)
        let resetsAt = now.addingTimeInterval(2 * 24 * 60 * 60)
        let referenceWindow = RateWindow(
            usedPercent: 50,
            windowMinutes: 10080,
            resetsAt: resetsAt,
            resetDescription: nil)
        let breakdown = Self.syntheticBreakdown(endingAt: now, days: 35, dailyCredits: 10)

        _ = await store.backfillCodexWeeklyFromUsageBreakdown(
            breakdown,
            referenceWindow: referenceWindow,
            now: now,
            accountKey: "acct-a")
        _ = await store.backfillCodexWeeklyFromUsageBreakdown(
            breakdown,
            referenceWindow: referenceWindow,
            now: now,
            accountKey: "acct-b")

        let records = try Self.readHistoricalRecords(from: fileURL)
        #expect(records.contains { $0.accountKey == "acct-a" })
        #expect(records.contains { $0.accountKey == "acct-b" })

        let aDataset = await store.loadCodexDataset(accountKey: "acct-a")
        let bDataset = await store.loadCodexDataset(accountKey: "acct-b")
        #expect((aDataset?.weeks.count ?? 0) >= 3)
        #expect((bDataset?.weeks.count ?? 0) >= 3)
    }

    @Test
    func `coverage tolerance allows day boundary shift without no op`() async {
        let fileURL = Self.makeTempURL()
        let store = HistoricalUsageHistoryStore(fileURL: fileURL)
        let now = Date(timeIntervalSince1970: 1_770_000_000)
        let breakdown = Self.syntheticBreakdown(endingAt: now, days: 35, dailyCredits: 10)

        let coverageStart = Self.dayStart(for: breakdown.last?.day ?? "")!
        let priorBackfillStart = coverageStart.addingTimeInterval(-10 * 60 * 60)
        let priorBackfillReset = priorBackfillStart.addingTimeInterval(7 * 24 * 60 * 60)
        let resetsAt = priorBackfillReset.addingTimeInterval(7 * 24 * 60 * 60)
        let referenceWindow = RateWindow(
            usedPercent: 50,
            windowMinutes: 10080,
            resetsAt: resetsAt,
            resetDescription: nil)

        let dataset = await store.backfillCodexWeeklyFromUsageBreakdown(
            breakdown,
            referenceWindow: referenceWindow,
            now: now,
            accountKey: nil)
        #expect((dataset?.weeks.count ?? 0) >= 1)
    }

    @Test
    func `backfill treats omitted recent zero usage days as coverage`() async {
        let fileURL = Self.makeTempURL()
        let store = HistoricalUsageHistoryStore(fileURL: fileURL)
        let now = Self.gregorianDate(year: 2026, month: 2, day: 26, hour: 20)
        let resetsAt = now.addingTimeInterval(2 * 24 * 60 * 60)
        let referenceWindow = RateWindow(
            usedPercent: 50,
            windowMinutes: 10080,
            resetsAt: resetsAt,
            resetDescription: nil)

        let breakdown = Self.syntheticBreakdown(
            endingAt: now,
            days: 35,
            dailyCredits: 10,
            overridesByDayOffset: [
                0: 0,
                1: 0,
            ])
            .filter { $0.totalCreditsUsed > 0 }

        let dataset = await store.backfillCodexWeeklyFromUsageBreakdown(
            breakdown,
            referenceWindow: referenceWindow,
            now: now,
            accountKey: nil)

        #expect((dataset?.weeks.count ?? 0) >= 3)
    }

    @Test
    func `backfill treats omitted leading zero usage days as coverage`() async {
        let fileURL = Self.makeTempURL()
        let store = HistoricalUsageHistoryStore(fileURL: fileURL)
        let now = Self.gregorianDate(year: 2026, month: 2, day: 26, hour: 20)
        let resetsAt = now.addingTimeInterval(2 * 24 * 60 * 60)
        let referenceWindow = RateWindow(
            usedPercent: 50,
            windowMinutes: 10080,
            resetsAt: resetsAt,
            resetDescription: nil)

        let breakdown = Self.syntheticBreakdown(
            endingAt: now,
            days: 35,
            dailyCredits: 10,
            overridesByDayOffset: [
                3: 0,
                4: 0,
                5: 0,
            ])
            .filter { $0.totalCreditsUsed > 0 }

        let dataset = await store.backfillCodexWeeklyFromUsageBreakdown(
            breakdown,
            referenceWindow: referenceWindow,
            now: now,
            accountKey: nil)

        #expect((dataset?.weeks.count ?? 0) >= 3)
    }

    @Test
    func `partial day credits are not undercounted at as of time`() {
        let asOf = Self.gregorianDate(year: 2026, month: 2, day: 26, hour: 12)
        let start = Self.gregorianDate(year: 2026, month: 2, day: 20, hour: 0)
        let breakdown = Self.syntheticBreakdown(
            endingAt: asOf,
            days: 35,
            dailyCredits: 1,
            overridesByDayOffset: [
                0: 20,
                7: 20,
            ])

        let credits = HistoricalUsageHistoryStore._creditsUsedForTesting(
            breakdown: breakdown,
            asOf: asOf,
            start: start,
            end: asOf)

        #expect(abs(credits - 26) < 0.001)
    }

    @Test
    func `gregorian day parsing is stable for YYYYMMDD`() {
        let parsed = HistoricalUsageHistoryStore._dayStartForTesting("2026-02-26")
        let expected = Self.gregorianDate(year: 2026, month: 2, day: 26, hour: 0)
        #expect(parsed == expected)
    }

    @MainActor
    @Test
    func `backfill skips when timestamp mismatch exceeds5 minutes`() async throws {
        let store = try Self.makeUsageStoreForBackfillTests(
            suite: "HistoricalUsagePaceTests-backfill-mismatch",
            historyFileURL: Self.makeTempURL())
        store._setCodexHistoricalDatasetForTesting(nil)

        let snapshotNow = Date(timeIntervalSince1970: 1_770_000_000)
        let weekly = RateWindow(
            usedPercent: 55,
            windowMinutes: 10080,
            resetsAt: snapshotNow.addingTimeInterval(2 * 24 * 60 * 60),
            resetDescription: nil)
        let snapshot = UsageSnapshot(
            primary: nil,
            secondary: weekly,
            tertiary: nil,
            providerCost: nil,
            updatedAt: snapshotNow,
            identity: nil)
        store._setSnapshotForTesting(snapshot, provider: .codex)

        let dashboard = OpenAIDashboardSnapshot(
            signedInEmail: nil,
            codeReviewRemainingPercent: nil,
            creditEvents: [],
            dailyBreakdown: [],
            usageBreakdown: Self.syntheticBreakdown(endingAt: snapshotNow, days: 35, dailyCredits: 10),
            creditsPurchaseURL: nil,
            primaryLimit: nil,
            secondaryLimit: nil,
            creditsRemaining: nil,
            accountPlan: nil,
            updatedAt: snapshotNow.addingTimeInterval(-10 * 60))
        store.backfillCodexHistoricalFromDashboardIfNeeded(
            dashboard,
            authorityDecision: CodexDashboardAuthorityDecision(
                disposition: .attach,
                reason: .trustedEmailMatchNoCompetingOwner,
                allowedEffects: [.historicalBackfill],
                cleanup: []),
            attachedAccountEmail: "attached@example.com")

        try await Task.sleep(for: .milliseconds(250))
        #expect(store.codexHistoricalDataset == nil)
    }

    @Test
    func `exhausted historical weeks extend linearly and don't flatline at 100`() throws {
        // Build a historical dataset where a week reaches 100% at u = 0.5
        var earlyExhaustedCurve = [Double]()
        for i in 0..<CodexHistoricalDataset.gridPointCount {
            let u = Double(i) / Double(CodexHistoricalDataset.gridPointCount - 1)
            if u <= 0.5 {
                earlyExhaustedCurve.append((u / 0.5) * 100)
            } else {
                earlyExhaustedCurve.append(100)
            }
        }
        let now = Date()
        let week = HistoricalWeekProfile(
            resetsAt: now.addingTimeInterval(-10080 * 60),
            windowMinutes: 10080,
            curve: earlyExhaustedCurve)
        let dataset = CodexHistoricalDataset(weeks: [week, week, week, week, week])

        let window = RateWindow(
            usedPercent: 80,
            windowMinutes: 10080,
            resetsAt: now.addingTimeInterval(0.25 * 10080 * 60),
            resetDescription: nil)

        let pace = try #require(CodexHistoricalPaceEvaluator.evaluate(
            window: window,
            now: now,
            dataset: dataset))

        #expect(pace.willLastToReset == false)
        #expect(pace.runOutProbability != nil)
        #expect(try #require(pace.runOutProbability) > 0)
        #expect(pace.deltaPercent > 0)

        let detail = UsagePaceText.weeklyDetail(provider: .codex, pace: pace, now: now)
        #expect(detail.leftLabel == "5% in deficit")
        #expect(detail.rightLabel?.contains("Lasts until reset") == false)
    }

    @Test
    func `exhausted actual returns zero eta`() throws {
        let now = Date()
        let resetsAt = now.addingTimeInterval(3600)
        let week = HistoricalWeekProfile(
            resetsAt: now.addingTimeInterval(-10080 * 60),
            windowMinutes: 10080,
            curve: Array(repeating: 100.0, count: 169))
        let dataset = CodexHistoricalDataset(weeks: [week, week, week])

        for usedPercent in [100.0, 120.0] {
            let window = RateWindow(
                usedPercent: usedPercent,
                windowMinutes: 10080,
                resetsAt: resetsAt,
                resetDescription: nil,
                nextRegenPercent: nil)

            let pace = try #require(CodexHistoricalPaceEvaluator.evaluate(
                window: window,
                now: now,
                dataset: dataset))
            #expect(pace.willLastToReset == false)
            #expect(pace.etaSeconds == 0)
            #expect(pace.runOutProbability == 1)

            let detail = UsagePaceText.weeklyDetail(provider: .codex, pace: pace, now: now)
            #expect(detail.rightLabel == "Runs out now (100% risk)")
        }
    }
}
