import SwiftUI

// Helper to allow dynamic shape switching
struct AnyShape: Shape {
    private let _path: (CGRect) -> Path
    
    init<S: Shape>(_ shape: S) {
        _path = { rect in
            shape.path(in: rect)
        }
    }
    
    func path(in rect: CGRect) -> Path {
        _path(rect)
    }
}

enum LargeButtonVariant {
    case primary
    case secondary
    case tertiary
    case secondaryElevated
    case aura
}

struct LargeButton: View {
    let title: String?
    let iconAssetName: String?
    let variant: LargeButtonVariant
    let action: () -> Void
    let isIconOnly: Bool
    
    init(
        title: String? = nil,
        iconAssetName: String? = nil,
        variant: LargeButtonVariant = .primary,
        action: @escaping () -> Void
    ) {
        self.title = title
        self.iconAssetName = iconAssetName
        self.variant = variant
        self.action = action
        self.isIconOnly = title == nil && iconAssetName != nil
    }
    
    var body: some View {
        Button(action: action) {
            if isIconOnly {
                // Icon-only button - 56x56
                if let iconAssetName = iconAssetName {
                    Image(iconAssetName)
                        .resizable()
                        .renderingMode(.template)
                        .foregroundColor(foregroundColor)
                        .frame(width: 24, height: 24)
                }
            } else {
                // Regular button with text and optional icon
                HStack(spacing: 4) {
                    if let iconAssetName = iconAssetName {
                        Image(iconAssetName)
                            .resizable()
                            .renderingMode(.template)
                            .foregroundColor(foregroundColor)
                            .frame(width: 16, height: 16)
                    }
                    
                    if let title = title {
                        Text(title)
                            .font(Constants.Typography.largeTitle)
                            .foregroundColor(foregroundColor)
                            .tracking(0.36)
                            .lineLimit(1)
                    }
                }
            }
        }
        .frame(width: isIconOnly ? 56 : nil, height: 56)
        .frame(maxWidth: isIconOnly ? nil : .infinity)
        .padding(.horizontal, isIconOnly ? 0 : 24)
        .background(backgroundView)
        .clipShape(isIconOnly ? AnyShape(Circle()) : AnyShape(Capsule()))
        .modifier(ButtonStyleModifier(variant: variant))
    }
    
    private var foregroundColor: Color {
        switch variant {
        case .primary:
            return Constants.Colors.Background.primary
        case .secondary, .tertiary, .secondaryElevated:
            return Constants.Colors.Foreground.primary
        case .aura:
            return Constants.Colors.Foreground.primary
        }
    }
    
    @ViewBuilder
    private var backgroundView: some View {
        switch variant {
        case .primary:
            Constants.Colors.Foreground.primary
        case .secondary:
            RoundedRectangle(cornerRadius: 100)
                .fill(Constants.Colors.Background.tertiary)
        case .tertiary:
            RoundedRectangle(cornerRadius: 100)
                .fill(Color.clear)
                .overlay(
                    RoundedRectangle(cornerRadius: 100)
                        .stroke(Color.white.opacity(0.1), lineWidth: 1)
                )
        case .secondaryElevated:
            RoundedRectangle(cornerRadius: 100)
                .fill(Constants.Colors.Background.Fog.thin)
        case .aura:
            Image("aura")
                .resizable()
                .aspectRatio(contentMode: .fill)
                .clipped()
        }
    }
}

// MARK: - Button Styles

struct AuraButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .scaleEffect(configuration.isPressed ? 0.96 : 1.0)
            .opacity(configuration.isPressed ? 0.9 : 1.0)
            .animation(.easeInOut(duration: 0.1), value: configuration.isPressed)
    }
}

// ViewModifier to apply different button styles
struct ButtonStyleModifier: ViewModifier {
    let variant: LargeButtonVariant
    
    func body(content: Content) -> some View {
        switch variant {
        case .primary, .secondary, .tertiary, .secondaryElevated:
            content.buttonStyle(PlainButtonStyle())
        case .aura:
            content.buttonStyle(AuraButtonStyle())
        }
    }
}

// MARK: - Convenience Initializers

extension LargeButton {
    /// Creates a secondary variant button
    static func secondary(
        _ title: String,
        iconName: String? = nil,
        action: @escaping () -> Void
    ) -> LargeButton {
        LargeButton(
            title: title,
            iconAssetName: iconName,
            variant: .secondary,
            action: action
        )
    }
    
    /// Creates a tertiary variant button
    static func tertiary(
        _ title: String,
        iconName: String? = nil,
        action: @escaping () -> Void
    ) -> LargeButton {
        LargeButton(
            title: title,
            iconAssetName: iconName,
            variant: .tertiary,
            action: action
        )
    }
    
    /// Creates a secondaryElevated variant button
    static func secondaryElevated(
        _ title: String,
        iconName: String? = nil,
        action: @escaping () -> Void
    ) -> LargeButton {
        LargeButton(
            title: title,
            iconAssetName: iconName,
            variant: .secondaryElevated,
            action: action
        )
    }
    
    /// Creates an Aura variant button (for backward compatibility)
    static func aura(
        _ title: String,
        iconName: String? = nil,
        action: @escaping () -> Void
    ) -> LargeButton {
        LargeButton(
            title: title,
            iconAssetName: iconName,
            variant: .aura,
            action: action
        )
    }
    
    // MARK: - Icon-only variants
    
    /// Creates an icon-only primary button (56x56)
    static func iconOnly(
        _ iconName: String,
        variant: LargeButtonVariant = .primary,
        action: @escaping () -> Void
    ) -> LargeButton {
        LargeButton(
            title: nil,
            iconAssetName: iconName,
            variant: variant,
            action: action
        )
    }
    
    /// Creates an icon-only secondary button (56x56)
    static func iconOnlySecondary(
        _ iconName: String,
        action: @escaping () -> Void
    ) -> LargeButton {
        LargeButton(
            title: nil,
            iconAssetName: iconName,
            variant: .secondary,
            action: action
        )
    }
    
    /// Creates an icon-only tertiary button (56x56)
    static func iconOnlyTertiary(
        _ iconName: String,
        action: @escaping () -> Void
    ) -> LargeButton {
        LargeButton(
            title: nil,
            iconAssetName: iconName,
            variant: .tertiary,
            action: action
        )
    }
    
    /// Creates an icon-only aura button (56x56)
    static func iconOnlyAura(
        _ iconName: String,
        action: @escaping () -> Void
    ) -> LargeButton {
        LargeButton(
            title: nil,
            iconAssetName: iconName,
            variant: .aura,
            action: action
        )
    }
    
    /// Creates an icon-only secondaryElevated button (56x56)
    static func iconOnlySecondaryElevated(
        _ iconName: String,
        action: @escaping () -> Void
    ) -> LargeButton {
        LargeButton(
            title: nil,
            iconAssetName: iconName,
            variant: .secondaryElevated,
            action: action
        )
    }
}

// MARK: - Preview
#Preview {
    VStack(spacing: 20) {
        // Regular buttons with text
        LargeButton(
            title: "Continue",
            iconAssetName: "Icon/create",
            variant: .primary,
            action: { print("Continue button tapped") }
        )
        
        LargeButton.secondary("Edit Prompt", iconName: "Icon/edit") {
            print("Edit Prompt button tapped")
        }
        
        LargeButton.tertiary("Tertiary", iconName: "Icon/create") {
            print("Tertiary button tapped")
        }
        
        LargeButton.secondaryElevated("Secondary Elevated", iconName: "Icon/create") {
            print("Secondary Elevated button tapped")
        }
        
        LargeButton.aura("Create", iconName: "Icon/create") {
            print("Create button tapped")
        }
        
        // Icon-only buttons (56x56)
        HStack(spacing: 16) {
            LargeButton.iconOnly("Icon/play") {
                print("Icon-only primary tapped")
            }
            
            LargeButton.iconOnlySecondary("Icon/pause") {
                print("Icon-only secondary tapped")
            }
            
            LargeButton.iconOnlyTertiary("Icon/close") {
                print("Icon-only tertiary tapped")
            }
            
            LargeButton.iconOnlyAura("Icon/create") {
                print("Icon-only aura tapped")
            }
            
            LargeButton.iconOnlySecondaryElevated("Icon/library") {
                print("Icon-only secondary elevated tapped")
            }
        }
    }
    .padding()
    .background(Constants.Colors.Background.primary)
}
