import CodexBarCore
import Foundation
import Testing
@testable import CodexBar

@Suite(.serialized)
struct CodexSystemAccountObserverTests {
    @Test
    func `observer reads ambient CODEX_HOME when present`() throws {
        let home = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString, isDirectory: true)
        defer { try? FileManager.default.removeItem(at: home) }
        try Self.writeCodexAuthFile(
            homeURL: home,
            email: "  LIVE@Example.com  ",
            plan: "pro",
            accountId: "account-live")

        let observer = DefaultCodexSystemAccountObserver()
        let account = try observer.loadSystemAccount(environment: ["CODEX_HOME": home.path])

        #expect(account?.email == "live@example.com")
        #expect(account?.codexHomePath == home.path)
        #expect(account?.identity == .providerAccount(id: "account-live"))
    }

    @Test
    func `observer falls back to nil when ambient home has no readable email`() throws {
        let home = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString, isDirectory: true)
        defer { try? FileManager.default.removeItem(at: home) }
        try FileManager.default.createDirectory(at: home, withIntermediateDirectories: true)

        let observer = DefaultCodexSystemAccountObserver()
        let account = try observer.loadSystemAccount(environment: ["CODEX_HOME": home.path])

        #expect(account == nil)
    }

    @Test
    func `observer records observation timestamp`() throws {
        let home = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString, isDirectory: true)
        defer { try? FileManager.default.removeItem(at: home) }
        try Self.writeCodexAuthFile(homeURL: home, email: "user@example.com", plan: "team")

        let before = Date()
        let observer = DefaultCodexSystemAccountObserver()
        let account = try observer.loadSystemAccount(environment: ["CODEX_HOME": home.path])
        let observed = try #require(account)

        #expect(observed.observedAt >= before)
    }

    @Test
    func `observer preserves provider account identity from scoped auth`() throws {
        let home = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString, isDirectory: true)
        defer { try? FileManager.default.removeItem(at: home) }
        try Self.writeCodexAuthFile(
            homeURL: home,
            email: "user@example.com",
            plan: "team",
            accountId: "account-live-123")

        let observer = DefaultCodexSystemAccountObserver()
        let account = try #require(try observer.loadSystemAccount(environment: ["CODEX_HOME": home.path]))

        #expect(account.identity == .providerAccount(id: "account-live-123"))
    }

    @Test
    func `observer uses cached workspace label for provider account`() throws {
        let home = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString, isDirectory: true)
        let cacheURL = FileManager.default.temporaryDirectory
            .appendingPathComponent("codex-openai-workspaces-\(UUID().uuidString).json")
        defer {
            try? FileManager.default.removeItem(at: home)
            try? FileManager.default.removeItem(at: cacheURL)
        }
        try Self.writeCodexAuthFile(
            homeURL: home,
            email: "user@example.com",
            plan: "team",
            accountId: "account-live-123")

        try CodexOpenAIWorkspaceIdentityCache.withFileURLOverrideForTesting(cacheURL) {
            try CodexOpenAIWorkspaceIdentityCache().store(CodexOpenAIWorkspaceIdentity(
                workspaceAccountID: "account-live-123",
                workspaceLabel: "Team Alpha"))

            let observer = DefaultCodexSystemAccountObserver()
            let account = try #require(try observer.loadSystemAccount(environment: ["CODEX_HOME": home.path]))

            #expect(account.workspaceAccountID == "account-live-123")
            #expect(account.workspaceLabel == "Team Alpha")
        }
    }

    private static func writeCodexAuthFile(
        homeURL: URL,
        email: String,
        plan: String,
        accountId: String? = nil) throws
    {
        try FileManager.default.createDirectory(at: homeURL, withIntermediateDirectories: true)
        var tokens: [String: Any] = [
            "accessToken": "access-token",
            "refreshToken": "refresh-token",
            "idToken": Self.fakeJWT(email: email, plan: plan),
        ]
        if let accountId {
            tokens["accountId"] = accountId
        }
        let auth = ["tokens": tokens]
        let data = try JSONSerialization.data(withJSONObject: auth)
        try data.write(to: homeURL.appendingPathComponent("auth.json"))
    }

    private static func fakeJWT(email: String, plan: String) -> String {
        let header = (try? JSONSerialization.data(withJSONObject: ["alg": "none"])) ?? Data()
        let payload = (try? JSONSerialization.data(withJSONObject: [
            "email": email,
            "chatgpt_plan_type": plan,
        ])) ?? Data()

        func base64URL(_ data: Data) -> String {
            data.base64EncodedString()
                .replacingOccurrences(of: "=", with: "")
                .replacingOccurrences(of: "+", with: "-")
                .replacingOccurrences(of: "/", with: "_")
        }

        return "\(base64URL(header)).\(base64URL(payload))."
    }
}
