import Foundation
import Testing
@testable import CodeBurnMenubar

@Suite("MenubarStatusCache")
struct MenubarStatusCacheTests {
    private func tempDir() -> String {
        let dir = NSTemporaryDirectory() + "menubar-status-test-" + UUID().uuidString
        try? FileManager.default.createDirectory(atPath: dir, withIntermediateDirectories: true)
        return dir
    }

    private func validPayloadJSON(cost: Double) -> Data {
        let p = MenubarPayload(
            generated: "2026-05-29T00:00:00Z",
            current: CurrentBlock(
                label: "Today", cost: cost, calls: 1, sessions: 1, oneShotRate: nil,
                inputTokens: 1, outputTokens: 1, cacheHitPercent: 0,
                codexCredits: nil,
                topActivities: [], topModels: [], localModelSavings: LocalModelSavings(totalUSD: 0, calls: 0, byModel: [], byProvider: []), providers: ["claude": cost],
                topProjects: [], modelEfficiency: [], topSessions: [],
                retryTax: RetryTax(totalUSD: 0, retries: 0, editTurns: 0, byModel: []),
                routingWaste: RoutingWaste(totalSavingsUSD: 0, baselineModel: "", baselineCostPerEdit: 0, byModel: []),
                tools: [], skills: [], subagents: [], mcpServers: []
            ),
            optimize: OptimizeBlock(findingCount: 0, savingsUSD: 0, topFindings: []),
            history: HistoryBlock(daily: []),
            combined: nil
        )
        return try! JSONEncoder().encode(p)
    }

    @Test("reads a fresh, valid status file")
    func readsValidFile() throws {
        let dir = tempDir()
        let path = dir + "/menubar-status.json"
        try validPayloadJSON(cost: 42.5).write(to: URL(fileURLWithPath: path))
        let cache = MenubarStatusCache(statusPath: path)

        let result = cache.readBadgePayload(maxAgeSeconds: 3600)

        #expect(result?.payload.current.cost == 42.5)
        #expect((result?.ageSeconds ?? .infinity) < 60)
    }

    @Test("returns nil for a missing file")
    func missingFileReturnsNil() {
        let dir = tempDir()
        let cache = MenubarStatusCache(statusPath: dir + "/nope.json")
        #expect(cache.readBadgePayload(maxAgeSeconds: 3600) == nil)
    }

    @Test("returns nil for a corrupt file")
    func corruptFileReturnsNil() throws {
        let dir = tempDir()
        let path = dir + "/menubar-status.json"
        try Data("{ not json".utf8).write(to: URL(fileURLWithPath: path))
        let cache = MenubarStatusCache(statusPath: path)
        #expect(cache.readBadgePayload(maxAgeSeconds: 3600) == nil)
    }

    @Test("returns nil for an over-age file")
    func overAgeFileReturnsNil() throws {
        let dir = tempDir()
        let path = dir + "/menubar-status.json"
        let url = URL(fileURLWithPath: path)
        try validPayloadJSON(cost: 7).write(to: url)
        try FileManager.default.setAttributes(
            [.modificationDate: Date().addingTimeInterval(-7200)], ofItemAtPath: path
        )
        let cache = MenubarStatusCache(statusPath: path)
        #expect(cache.readBadgePayload(maxAgeSeconds: 3600) == nil)
    }

    @Test("writeStatus round-trips through readBadgePayload")
    func writeStatusRoundTrips() throws {
        let dir = tempDir()
        let path = dir + "/menubar-status.json"
        let cache = MenubarStatusCache(statusPath: path)

        let payload = try JSONDecoder().decode(MenubarPayload.self, from: validPayloadJSON(cost: 13.5))
        try cache.writeStatus(payload)

        let result = cache.readBadgePayload(maxAgeSeconds: 3600)
        #expect(result?.payload.current.cost == 13.5)
    }
}
