//
//  MiniMaxServiceUsage.swift
//  CodexBarCore
//
//  Created by Sisyphus on 2026-03-25.
//

import Foundation

/// Represents the usage information for a specific MiniMax service.
///
/// This struct encapsulates all the relevant details about how much of a particular
/// MiniMax service has been used within its quota window, including reset timing
/// and localized display strings.
public struct MiniMaxServiceUsage: Sendable {
    /// The service identifier (e.g., "text-generation", "text-to-speech", "image")
    public let serviceType: String

    /// The type of time window for the quota (e.g., "5 hours" or "Today")
    /// This should be a localized string.
    public let windowType: String

    /// The specific time range for the current quota window.
    /// For hourly quotas: "10:00-15:00(UTC+8)"
    /// For daily quotas: full date range string
    public let timeRange: String

    /// The amount of quota that has been used.
    public let usage: Int

    /// The total quota limit for this service in the current window
    public let limit: Int

    /// The percentage of quota used (0-100)
    public let percent: Double

    /// Whether this quota window is explicitly unlimited.
    public let isUnlimited: Bool

    /// The timestamp when the quota will reset, if available
    public let resetsAt: Date?

    /// A localized description of when the quota resets (e.g., "Resets in 2 hours 30 minutes")
    public let resetDescription: String

    /// The remaining quota available (limit - usage)
    public var remaining: Int {
        max(0, self.limit - self.usage)
    }

    /// The display name for this service
    public var displayName: String {
        let normalized = self.serviceType.lowercased()
        return switch normalized {
        case "general":
            "General"
        case "video":
            "Video"
        case "text-generation":
            "Text Generation"
        case "text-to-speech":
            "Text to Speech"
        case "image":
            "Image"
        case "text generation":
            "Text Generation"
        case "text to speech":
            "Text to Speech"
        case "image generation":
            "Image Generation"
        case "text to video":
            "Text to Video"
        case "image to video":
            "Image to Video"
        case "music generation":
            "Music Generation"
        case "music generation · v2.6":
            "Music Generation · v2.6"
        case "music cover":
            "Music Cover"
        case "lyrics generation":
            "Lyrics Generation"
        case "image understanding":
            "Image Understanding"
        default:
            self.serviceType
        }
    }

    public var isPrimaryTextQuotaLane: Bool {
        let normalized = self.serviceType.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
        return normalized == "general" || self.displayName == "Text Generation"
    }

    /// Creates a new MiniMaxServiceUsage instance.
    ///
    /// - Parameters:
    ///   - serviceType: The service identifier
    ///   - windowType: The type of time window (localized)
    ///   - timeRange: The specific time range string
    ///   - usage: The amount of quota used
    ///   - limit: The total quota limit
    ///   - percent: The percentage used (0-100)
    ///   - resetsAt: Optional reset timestamp
    ///   - resetDescription: Localized reset description
    public init(
        serviceType: String,
        windowType: String,
        timeRange: String,
        usage: Int,
        limit: Int,
        percent: Double,
        isUnlimited: Bool = false,
        resetsAt: Date?,
        resetDescription: String)
    {
        self.serviceType = serviceType
        self.windowType = windowType
        self.timeRange = timeRange
        self.usage = usage
        self.limit = limit
        self.percent = percent
        self.isUnlimited = isUnlimited
        self.resetsAt = resetsAt
        self.resetDescription = resetDescription
    }
}

extension MiniMaxServiceUsage {
    public static func parseWindowType(_ windowType: String) -> (windowType: String, windowMinutes: Int?) {
        switch windowType.lowercased() {
        case "5 hours", "5 小时":
            return ("5 hours", 300)
        case "today", "今日":
            return ("Today", 1440)
        default:
            // Try to extract hours from string like "X hours"
            if let hours = Int(windowType.components(separatedBy: .whitespaces).first ?? "") {
                return (windowType, hours * 60)
            }
            return (windowType, nil)
        }
    }

    public static func parseTimeRange(_ timeRange: String, now: Date) -> Date? {
        let calendar = Calendar.current

        // Handle "10:00-15:00(UTC+8)" format
        if timeRange.contains("-"), timeRange.contains("("), timeRange.contains(")") {
            // Extract the time part before the timezone
            let components = timeRange.split(separator: "(")
            guard components.count >= 1 else { return nil }
            let timePart = String(components[0]).trimmingCharacters(in: .whitespaces)

            // Split by "-" to get start and end times
            let timeComponents = timePart.split(separator: "-")
            guard timeComponents.count == 2 else { return nil }

            let endTimeStr = String(timeComponents[1]).trimmingCharacters(in: .whitespaces)

            // Parse end time (HH:mm format)
            let timeFormatter = DateFormatter()
            timeFormatter.dateFormat = "HH:mm"
            timeFormatter.timeZone = TimeZone.current

            guard let endTime = timeFormatter.date(from: endTimeStr) else { return nil }

            // Get today's date components
            let nowComponents = calendar.dateComponents([.year, .month, .day], from: now)
            let endTimeComponents = calendar.dateComponents([.hour, .minute], from: endTime)

            // Combine today's date with end time
            var combinedComponents = DateComponents()
            combinedComponents.year = nowComponents.year
            combinedComponents.month = nowComponents.month
            combinedComponents.day = nowComponents.day
            combinedComponents.hour = endTimeComponents.hour
            combinedComponents.minute = endTimeComponents.minute

            guard let resultDate = calendar.date(from: combinedComponents) else { return nil }

            // If the result date is in the past (before now), add one day
            if resultDate < now {
                return calendar.date(byAdding: .day, value: 1, to: resultDate)
            }

            return resultDate
        }

        // Handle "2026/03/25 00:00 - 2026/03/26 00:00" format
        if timeRange.contains(" - ") {
            let dateComponents = timeRange.split(separator: " - ")
            guard dateComponents.count == 2 else { return nil }

            let endDateStr = String(dateComponents[1]).trimmingCharacters(in: .whitespaces)

            let dateFormatter = DateFormatter()
            dateFormatter.dateFormat = "yyyy/MM/dd HH:mm"
            dateFormatter.timeZone = TimeZone.current

            return dateFormatter.date(from: endDateStr)
        }

        return nil
    }

    public static func generateResetDescription(resetsAt: Date, now: Date = Date()) -> String {
        let calendar = Calendar.current
        let components = calendar.dateComponents([.hour, .minute], from: now, to: resetsAt)

        guard let hours = components.hour, let minutes = components.minute else {
            return "Resets soon"
        }

        if hours > 0, minutes > 0 {
            return "Resets in \(hours) hours \(minutes) minutes"
        } else if hours > 0 {
            return "Resets in \(hours) hour\(hours > 1 ? "s" : "")"
        } else if minutes > 0 {
            return "Resets in \(minutes) minute\(minutes > 1 ? "s" : "")"
        } else {
            return "Resets now"
        }
    }
}
