import Foundation

public struct ObservedSystemCodexAccount: Equatable, Sendable {
    public let email: String
    public let workspaceLabel: String?
    public let workspaceAccountID: String?
    public let authFingerprint: String?
    public let codexHomePath: String
    public let observedAt: Date
    public let identity: CodexIdentity

    public init(
        email: String,
        workspaceLabel: String? = nil,
        workspaceAccountID: String? = nil,
        authFingerprint: String? = nil,
        codexHomePath: String,
        observedAt: Date,
        identity: CodexIdentity = .unresolved)
    {
        self.email = email
        self.workspaceLabel = workspaceLabel
        self.workspaceAccountID = workspaceAccountID
        self.authFingerprint = CodexAuthFingerprint.normalize(authFingerprint)
        self.codexHomePath = codexHomePath
        self.observedAt = observedAt
        self.identity = identity
    }
}

public protocol CodexSystemAccountObserving: Sendable {
    func loadSystemAccount(environment: [String: String]) throws -> ObservedSystemCodexAccount?
}

public struct DefaultCodexSystemAccountObserver: CodexSystemAccountObserving {
    private let workspaceCache: CodexOpenAIWorkspaceIdentityCache

    public init(workspaceCache: CodexOpenAIWorkspaceIdentityCache = CodexOpenAIWorkspaceIdentityCache()) {
        self.workspaceCache = workspaceCache
    }

    public func loadSystemAccount(environment: [String: String]) throws -> ObservedSystemCodexAccount? {
        let homeURL = CodexHomeScope.ambientHomeURL(env: environment)
        let fetcher = UsageFetcher(environment: environment)
        let account = fetcher.loadAuthBackedCodexAccount()

        guard let rawEmail = account.email?.trimmingCharacters(in: .whitespacesAndNewlines),
              !rawEmail.isEmpty
        else {
            return nil
        }

        let providerAccountID: String? = switch account.identity {
        case let .providerAccount(id):
            ManagedCodexAccount.normalizeProviderAccountID(id)
        case .emailOnly, .unresolved:
            nil
        }

        return ObservedSystemCodexAccount(
            email: rawEmail.lowercased(),
            workspaceLabel: self.workspaceCache.workspaceLabel(for: providerAccountID),
            workspaceAccountID: providerAccountID,
            authFingerprint: CodexAuthFingerprint.fingerprint(homePath: homeURL.path),
            codexHomePath: homeURL.path,
            observedAt: Date(),
            identity: account.identity)
    }
}
