import SwiftUI

extension Color {
    // MARK: - Hex Initialization

    init?(hex: String) {
        var hexSanitized = hex.trimmingCharacters(in: .whitespacesAndNewlines)
        hexSanitized = hexSanitized.replacingOccurrences(of: "#", with: "")

        var rgb: UInt64 = 0

        guard Scanner(string: hexSanitized).scanHexInt64(&rgb) else {
            return nil
        }

        let length = hexSanitized.count

        switch length {
        case 6:
            self.init(
                red: Double((rgb & 0xFF0000) >> 16) / 255.0,
                green: Double((rgb & 0x00FF00) >> 8) / 255.0,
                blue: Double(rgb & 0x0000FF) / 255.0
            )
        case 8:
            self.init(
                red: Double((rgb & 0xFF000000) >> 24) / 255.0,
                green: Double((rgb & 0x00FF0000) >> 16) / 255.0,
                blue: Double((rgb & 0x0000FF00) >> 8) / 255.0,
                opacity: Double(rgb & 0x000000FF) / 255.0
            )
        default:
            return nil
        }
    }

    // MARK: - Hex String Output

    var hexString: String {
        guard let components = UIColor(self).cgColor.components else {
            return "#000000"
        }

        let r = Int(components[0] * 255.0)
        let g = Int(components[1] * 255.0)
        let b = Int(components[2] * 255.0)

        return String(format: "#%02X%02X%02X", r, g, b)
    }

    // MARK: - App Colors

    static let appPrimary = Color(hex: "#3B82F6") ?? .blue
    static let appSecondary = Color(hex: "#10B981") ?? .green
    static let appAccent = Color(hex: "#F59E0B") ?? .orange
    static let appError = Color(hex: "#EF4444") ?? .red
    static let appSuccess = Color(hex: "#10B981") ?? .green
    static let appWarning = Color(hex: "#F59E0B") ?? .orange

    // MARK: - Financial Colors

    static let positiveGreen = Color(hex: "#10B981") ?? .green
    static let negativeRed = Color(hex: "#EF4444") ?? .red
    static let neutralGray = Color(hex: "#6B7280") ?? .gray

    static func financialColor(for value: Decimal) -> Color {
        if value > 0 {
            return .positiveGreen
        } else if value < 0 {
            return .negativeRed
        } else {
            return .neutralGray
        }
    }

    static func financialColor(for value: Double) -> Color {
        if value > 0 {
            return .positiveGreen
        } else if value < 0 {
            return .negativeRed
        } else {
            return .neutralGray
        }
    }

    // MARK: - Category Colors

    static let categoryColors: [String] = [
        "#3B82F6", // Blue
        "#10B981", // Green
        "#F59E0B", // Amber
        "#EF4444", // Red
        "#8B5CF6", // Purple
        "#EC4899", // Pink
        "#14B8A6", // Teal
        "#F97316", // Orange
        "#6366F1", // Indigo
        "#84CC16", // Lime
        "#06B6D4", // Cyan
        "#A855F7"  // Violet
    ]

    static func categoryColor(at index: Int) -> Color {
        let hex = categoryColors[index % categoryColors.count]
        return Color(hex: hex) ?? .blue
    }

    // MARK: - Source Colors (distinct per-source palette, different order from categories)

    static let sourceColors: [String] = [
        "#6366F1", // Indigo
        "#F97316", // Orange
        "#06B6D4", // Cyan
        "#EF4444", // Red
        "#84CC16", // Lime
        "#EC4899", // Pink
        "#14B8A6", // Teal
        "#F59E0B", // Amber
        "#8B5CF6", // Purple
        "#3B82F6", // Blue
        "#A855F7", // Violet
        "#10B981", // Green
    ]

    static func sourceColor(at index: Int) -> Color {
        let hex = sourceColors[index % sourceColors.count]
        return Color(hex: hex) ?? .blue
    }

    // MARK: - Chart Colors

    static let chartColors: [Color] = categoryColors.compactMap { Color(hex: $0) }

    // MARK: - Adjustments

    func lighter(by percentage: Double = 0.2) -> Color {
        adjustBrightness(by: abs(percentage))
    }

    func darker(by percentage: Double = 0.2) -> Color {
        adjustBrightness(by: -abs(percentage))
    }

    private func adjustBrightness(by percentage: Double) -> Color {
        var hue: CGFloat = 0
        var saturation: CGFloat = 0
        var brightness: CGFloat = 0
        var alpha: CGFloat = 0

        UIColor(self).getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha)

        let newBrightness = max(0, min(1, brightness + CGFloat(percentage)))

        return Color(UIColor(hue: hue, saturation: saturation, brightness: newBrightness, alpha: alpha))
    }

    // MARK: - Opacity Variants

    var soft: Color {
        self.opacity(0.1)
    }

    var medium: Color {
        self.opacity(0.5)
    }
}

// MARK: - Gradient Extensions

extension LinearGradient {
    static let appPrimaryGradient = LinearGradient(
        colors: [Color.appPrimary, Color.appPrimary.lighter()],
        startPoint: .topLeading,
        endPoint: .bottomTrailing
    )

    static let positiveGradient = LinearGradient(
        colors: [Color.positiveGreen.lighter(), Color.positiveGreen],
        startPoint: .top,
        endPoint: .bottom
    )

    static let negativeGradient = LinearGradient(
        colors: [Color.negativeRed.lighter(), Color.negativeRed],
        startPoint: .top,
        endPoint: .bottom
    )
}
