import SwiftUI

// MARK: - Design System
// Modern, sleek design system for honeyDue with Light and Dark mode support

// MARK: - Reactive Theme Source

#if WIDGET_EXTENSION
// Widgets: read directly from UserDefaults (no reactivity needed)
enum AppThemeSource {
    private static let defaults: UserDefaults = {
        let groupID = Bundle.main.infoDictionary?["AppGroupIdentifier"] as? String
        return groupID.flatMap { UserDefaults(suiteName: $0) } ?? .standard
    }()

    static var themeName: String {
        defaults.string(forKey: "selectedTheme") ?? ThemeID.bright.rawValue
    }

    static var honeycombEnabled: Bool {
        defaults.bool(forKey: "honeycombEnabled")
    }
}
#else
/// Observable theme source that SwiftUI automatically tracks.
/// When `themeName` changes, all views using `Color.appPrimary` etc. re-render.
@Observable
final class AppThemeSource {
    static let shared = AppThemeSource()

    var themeName: String
    var honeycombEnabled: Bool

    private init() {
        let groupID = Bundle.main.infoDictionary?["AppGroupIdentifier"] as? String
        let defaults = groupID.flatMap { UserDefaults(suiteName: $0) } ?? .standard
        self.themeName = defaults.string(forKey: "selectedTheme") ?? ThemeID.bright.rawValue
        self.honeycombEnabled = defaults.bool(forKey: "honeycombEnabled")
    }
}
#endif

// MARK: - Colors

extension Color {
    // MARK: - Dynamic Theme Resolution

    private static func themed(_ name: String) -> Color {
        #if WIDGET_EXTENSION
        let theme = AppThemeSource.themeName
        #else
        let theme = AppThemeSource.shared.themeName
        #endif
        return Color("\(theme)/\(name)", bundle: nil)
    }

    // MARK: - Semantic Colors (Use These in UI)
    // Main app: resolved via @Observable AppThemeSource — views auto-update on theme change.
    // Widgets: resolved via UserDefaults (static, no reactivity needed).
    static var appPrimary: Color { themed("Primary") }
    static var appSecondary: Color { themed("Secondary") }
    static var appAccent: Color { themed("Accent") }
    static var appBackgroundPrimary: Color { themed("BackgroundPrimary") }
    static var appBackgroundSecondary: Color { themed("BackgroundSecondary") }
    static var appError: Color { themed("Error") }
    static var appTextPrimary: Color { themed("TextPrimary") }
    static var appTextSecondary: Color { themed("TextSecondary") }
    static var appTextOnPrimary: Color { themed("TextOnPrimary") }

    // MARK: - Hex Support
    init?(hex: String) {
        let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
        var int: UInt64 = 0
        Scanner(string: hex).scanHexInt64(&int)
        let a, r, g, b: UInt64
        switch hex.count {
        case 3: // RGB (12-bit)
            (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
        case 6: // RGB (24-bit)
            (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
        case 8: // ARGB (32-bit)
            (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
        default:
            return nil
        }

        self.init(
            .sRGB,
            red: Double(r) / 255,
            green: Double(g) / 255,
            blue:  Double(b) / 255,
            opacity: Double(a) / 255
        )
    }
}

// MARK: - Spacing

struct AppSpacing {
    static let xxs: CGFloat = 4
    static let xs: CGFloat = 8
    static let sm: CGFloat = 12
    static let md: CGFloat = 16
    static let lg: CGFloat = 24
    static let xl: CGFloat = 32
    static let xxl: CGFloat = 48
    static let xxxl: CGFloat = 64
}

struct AppRadius {
    static let xs: CGFloat = 4
    static let sm: CGFloat = 8
    static let md: CGFloat = 12
    static let lg: CGFloat = 16
    static let xl: CGFloat = 20
    static let xxl: CGFloat = 24
    static let full: CGFloat = 9999
}

struct AppShadow {
    static let sm = Shadow(color: .black.opacity(0.05), radius: 2, y: 1)
    static let md = Shadow(color: .black.opacity(0.1), radius: 4, y: 2)
    static let lg = Shadow(color: .black.opacity(0.1), radius: 8, y: 4)
    static let xl = Shadow(color: .black.opacity(0.15), radius: 16, y: 8)

    struct Shadow {
        let color: Color
        let radius: CGFloat
        let x: CGFloat
        let y: CGFloat

        init(color: Color, radius: CGFloat, x: CGFloat = 0, y: CGFloat) {
            self.color = color
            self.radius = radius
            self.x = x
            self.y = y
        }
    }
}

// MARK: - View Modifiers

struct CardStyle: ViewModifier {
    var shadow: AppShadow.Shadow = AppShadow.md
    var padding: CGFloat = AppSpacing.md

    func body(content: Content) -> some View {
        content
            .background(Color.appBackgroundSecondary)
            .cornerRadius(AppRadius.lg)
            .shadow(color: shadow.color, radius: shadow.radius, x: shadow.x, y: shadow.y)
    }
}

struct PrimaryButtonStyle: ButtonStyle {
    var isLoading: Bool = false

    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .font(.headline)
            .foregroundColor(.appTextOnPrimary)
            .frame(maxWidth: .infinity)
            .frame(height: 56)
            .background(
                configuration.isPressed ? Color.appPrimary.opacity(0.8) : Color.appPrimary
            )
            .cornerRadius(AppRadius.md)
            .scaleEffect(configuration.isPressed ? 0.98 : 1.0)
            .animation(.easeInOut(duration: 0.1), value: configuration.isPressed)
    }
}

struct SecondaryButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .font(.headline)
            .foregroundColor(.appPrimary)
            .frame(maxWidth: .infinity)
            .frame(height: 56)
            .background(Color.appPrimary.opacity(0.1))
            .cornerRadius(AppRadius.md)
            .scaleEffect(configuration.isPressed ? 0.98 : 1.0)
            .animation(.easeInOut(duration: 0.1), value: configuration.isPressed)
    }
}

struct TextFieldStyle: ViewModifier {
    func body(content: Content) -> some View {
        content
            .padding(AppSpacing.md)
            .background(Color.appBackgroundSecondary)
            .cornerRadius(AppRadius.md)
            .overlay(
                RoundedRectangle(cornerRadius: AppRadius.md)
                    .stroke(Color.appTextSecondary.opacity(0.3), lineWidth: 1)
            )
    }
}

// MARK: - View Extensions

extension View {
    func cardStyle(shadow: AppShadow.Shadow = AppShadow.md) -> some View {
        modifier(CardStyle(shadow: shadow))
    }

    func textFieldStyle() -> some View {
        modifier(TextFieldStyle())
    }
}

