import Foundation

struct GatewayUsageWindow: Codable {
    let label: String
    let usedPercent: Double
    let resetAt: Double?
}

struct GatewayUsageProvider: Codable {
    let provider: String
    let displayName: String
    let windows: [GatewayUsageWindow]
    let plan: String?
    let error: String?
}

struct GatewayUsageSummary: Codable {
    let updatedAt: Double
    let providers: [GatewayUsageProvider]
}

struct UsageRow: Identifiable {
    let id: String
    let providerId: String
    let displayName: String
    let plan: String?
    let windowLabel: String?
    let usedPercent: Double?
    let resetAt: Date?
    let error: String?

    var hasError: Bool {
        if let error, !error.isEmpty { return true }
        return false
    }

    var titleText: String {
        if let plan, !plan.isEmpty { return "\(self.displayName) (\(plan))" }
        return self.displayName
    }

    var remainingPercent: Int? {
        guard let usedPercent, usedPercent.isFinite else { return nil }
        let remaining = max(0, min(100, Int(round(100 - usedPercent))))
        return remaining
    }

    func detailText(now: Date = .init()) -> String {
        guard let remaining = self.remainingPercent else { return "No data" }
        var parts = ["\(remaining)% left"]
        if let windowLabel, !windowLabel.isEmpty { parts.append(windowLabel) }
        if let resetAt {
            let reset = UsageRow.formatResetRemaining(target: resetAt, now: now)
            if let reset { parts.append("⏱\(reset)") }
        }
        return parts.joined(separator: " · ")
    }

    private static func formatResetRemaining(target: Date, now: Date) -> String? {
        let diff = target.timeIntervalSince(now)
        if diff <= 0 { return "now" }
        let minutes = Int(floor(diff / 60))
        if minutes < 60 { return "\(minutes)m" }
        let hours = minutes / 60
        let mins = minutes % 60
        if hours < 24 { return mins > 0 ? "\(hours)h \(mins)m" : "\(hours)h" }
        let days = hours / 24
        if days < 7 { return "\(days)d \(hours % 24)h" }
        let formatter = DateFormatter()
        formatter.dateFormat = "MMM d"
        return formatter.string(from: target)
    }
}

extension GatewayUsageSummary {
    func primaryRows() -> [UsageRow] {
        self.providers.compactMap { provider in
            guard let window = provider.windows.max(by: { $0.usedPercent < $1.usedPercent }) else {
                return nil
            }

            return UsageRow(
                id: "\(provider.provider)-\(window.label)",
                providerId: provider.provider,
                displayName: provider.displayName,
                plan: provider.plan,
                windowLabel: window.label,
                usedPercent: window.usedPercent,
                resetAt: window.resetAt.map { Date(timeIntervalSince1970: $0 / 1000) },
                error: nil)
        }
    }
}

@MainActor
enum UsageLoader {
    static func loadSummary() async throws -> GatewayUsageSummary {
        let data = try await ControlChannel.shared.request(
            method: "usage.status",
            params: nil,
            timeoutMs: 5000)
        return try JSONDecoder().decode(GatewayUsageSummary.self, from: data)
    }
}
