149 lines · 5.5 KB · Swift
RawDownload
import Foundation /// Parsed view of a Codebuff usage + subscription response pair.public struct CodebuffUsageSnapshot: Sendable {    public let creditsUsed: Double?    public let creditsTotal: Double?    public let creditsRemaining: Double?    public let weeklyUsed: Double?    public let weeklyLimit: Double?    public let weeklyResetsAt: Date?    public let billingPeriodEnd: Date?    public let nextQuotaReset: Date?    public let tier: String?    public let subscriptionStatus: String?    public let autoTopUpEnabled: Bool?    public let accountEmail: String?    public let updatedAt: Date     public init(        creditsUsed: Double? = nil,        creditsTotal: Double? = nil,        creditsRemaining: Double? = nil,        weeklyUsed: Double? = nil,        weeklyLimit: Double? = nil,        weeklyResetsAt: Date? = nil,        billingPeriodEnd: Date? = nil,        nextQuotaReset: Date? = nil,        tier: String? = nil,        subscriptionStatus: String? = nil,        autoTopUpEnabled: Bool? = nil,        accountEmail: String? = nil,        updatedAt: Date = Date())    {        self.creditsUsed = creditsUsed        self.creditsTotal = creditsTotal        self.creditsRemaining = creditsRemaining        self.weeklyUsed = weeklyUsed        self.weeklyLimit = weeklyLimit        self.weeklyResetsAt = weeklyResetsAt        self.billingPeriodEnd = billingPeriodEnd        self.nextQuotaReset = nextQuotaReset        self.tier = tier        self.subscriptionStatus = subscriptionStatus        self.autoTopUpEnabled = autoTopUpEnabled        self.accountEmail = accountEmail        self.updatedAt = updatedAt    }     public func toUsageSnapshot() -> UsageSnapshot {        let primary = self.makeCreditsWindow()        let secondary = self.makeWeeklyWindow()         let identity = ProviderIdentitySnapshot(            providerID: .codebuff,            accountEmail: self.accountEmail,            accountOrganization: nil,            loginMethod: self.makeLoginMethod())         return UsageSnapshot(            primary: primary,            secondary: secondary,            tertiary: nil,            providerCost: nil,            updatedAt: self.updatedAt,            identity: identity)    }     private func makeCreditsWindow() -> RateWindow? {        let total = self.resolvedTotal        guard let total, total > 0 else {            if self.creditsRemaining != nil || self.creditsUsed != nil {                // Degenerate case: no usable quota in the payload. Surface the row as fully                // exhausted so missing quota data is visibly surfaced (matches Kilo's behaviour                // for zero/unknown totals) rather than rendering a misleading healthy bar.                return RateWindow(                    usedPercent: 100,                    windowMinutes: nil,                    resetsAt: self.nextQuotaReset,                    resetDescription: nil)            }            return nil        }        let used = self.resolvedUsed        let percent = UsagePercent(used: used, limit: total).displayClamped        // Note: do not stuff the credit balance ("X/Y credits") into `resetDescription` —        // generic renderers (UsageFormatter.resetLine) prepend "Resets " when `resetsAt`        // is absent, which would surface misleading text like "Resets 250/1,000 credits".        // The credits detail is shown via the dedicated Codebuff account panel instead.        return RateWindow(            usedPercent: percent,            windowMinutes: nil,            resetsAt: self.nextQuotaReset,            resetDescription: nil)    }     private func makeWeeklyWindow() -> RateWindow? {        guard let limit = self.weeklyLimit, limit > 0 else { return nil }        let used = max(0, self.weeklyUsed ?? 0)        let percent = UsagePercent(used: used, limit: limit).displayClamped        // Same reasoning as above: avoid encoding non-reset detail in `resetDescription`.        return RateWindow(            usedPercent: percent,            windowMinutes: 7 * 24 * 60,            resetsAt: self.weeklyResetsAt,            resetDescription: nil)    }     private var resolvedTotal: Double? {        if let creditsTotal {            return max(0, creditsTotal)        }        if let creditsUsed, let creditsRemaining {            return max(0, creditsUsed + creditsRemaining)        }        return nil    }     private var resolvedUsed: Double {        if let creditsUsed {            return max(0, creditsUsed)        }        if let total = self.resolvedTotal, let creditsRemaining {            return max(0, total - creditsRemaining)        }        return 0    }     private func makeLoginMethod() -> String? {        var parts: [String] = []        if let tier = self.tier?.trimmingCharacters(in: .whitespacesAndNewlines), !tier.isEmpty {            parts.append(tier.capitalized)        }        if let remaining = self.creditsRemaining {            parts.append("\(Self.compactNumber(remaining)) remaining")        }        if self.autoTopUpEnabled == true {            parts.append("auto top-up")        }        return parts.isEmpty ? nil : parts.joined(separator: " · ")    }     static func compactNumber(_ value: Double) -> String {        let formatter = NumberFormatter()        formatter.numberStyle = .decimal        formatter.locale = Locale(identifier: "en_US")        formatter.maximumFractionDigits = value >= 1000 ? 0 : 1        return formatter.string(from: NSNumber(value: value)) ?? String(format: "%.0f", value)    }}