import ComponentLibrary
import ComposableArchitecture
import Foundation
import SwiftUI

public struct ActionButton: View {
    let icon: AnyView
    let label: String?
    let isHighlighted: Bool
    let highlightColor: Color
    let isMore: Bool
    let action: () -> Void
    let shouldAnimateOnTap: Bool
    let tooltip: Tooltip?
    let tooltipAccentColor: Color?
    let tooltipDismissedAction: (() -> Void)?

    @State private var isAnimating: Bool = false

    public init(
        icon: some View,
        isHighlighted: Bool = false,
        highlightColor: Color = .SemanticV2.accentPink,
        label: String? = nil,
        isMore: Bool = false,
        shouldAnimateOnTap: Bool = false,
        tooltip: Tooltip? = nil,
        tooltipAccentColor: Color? = nil,
        tooltipDismissedAction: (() -> Void)? = nil,
        action: @escaping () -> Void
    ) {
        self.icon = AnyView(icon)
        self.isHighlighted = isHighlighted
        self.highlightColor = highlightColor
        self.label = label
        self.isMore = isMore
        self.shouldAnimateOnTap = shouldAnimateOnTap
        self.tooltip = tooltip
        self.tooltipAccentColor = tooltipAccentColor
        self.tooltipDismissedAction = tooltipDismissedAction
        self.action = action
    }

    // MARK: - Styles

    @ViewBuilder
    private var background: some View {
        if isHighlighted {
            Circle().fill(Color.SemanticV2.omniplayerWhite)
        } else {
            Circle().fill(.ultraThinMaterial)
        }
    }

    private var iconStyle: some ShapeStyle {
        if isHighlighted {
            return AnyShapeStyle(highlightColor.gradient)
        } else {
            return AnyShapeStyle(Color.SemanticV1.iconPrimary)
        }
    }

    // MARK: - Body

    public var body: some View {
        VStack(spacing: 4) {
            if #available(iOS 26.0, *) {
                buttonGlass
            } else {
                buttonFallback
            }

            if let label {
                Text(label)
                    .foregroundColor(Color.SemanticV1.iconPrimary)
                    .typographyV1(labelFont)
                    .allowsHitTesting(false)
                    .contentTransition(.numericText())
                    .scaleEffect(isAnimating ? 2.0 : 1.0)
                    .animation(.bouncy, value: isAnimating)
                    .shadow(color: Color.SemanticV2.backgroundDarkOverlay, radius: 4.0)
                    .zIndex(-1)
            }
        }
        .fixedSize(horizontal: true, vertical: false)
    }

    // MARK: - Buttons

    @available(iOS 26.0, *)
    private var buttonGlass: some View {
        Button {
            handleTap()
        } label: {
            icon
                .foregroundStyle(iconStyle)
                .frame(width: 24, height: 24)
                .rotationEffect(isAnimating ? .degrees(-15) : .zero)
                .scaleEffect(isAnimating ? 1.5 : 1.0)
                .frame(width: 44, height: 44)
                .contentShape(.rect)
                .background(isHighlighted ? Color.SemanticV2.omniplayerWhite.opacity(0.9) : .clear)
                .clipShape(.circle)
                .glassEffect(.regular.interactive())
                .animation(.bouncy(extraBounce: 0.2), value: isAnimating)
                .animation(.easeInOut(duration: 0.3), value: isHighlighted)
        }
        .buttonStyle(.plain)
        .maybeTooltip(
            isMore: isMore,
            tooltip: tooltip,
            tooltipAccentColor: tooltipAccentColor,
            tooltipDismissedAction: tooltipDismissedAction
        )
    }

    private var buttonFallback: some View {
        Button {
            handleTap()
        } label: {
            Circle()
                .strokeBorder(Color.SemanticV2.backgroundGlassDense, lineWidth: 0.25, antialiased: true)
                .background(background)
                .frame(width: 44, height: 44)
                .overlay {
                    icon
                        .foregroundStyle(iconStyle)
                        .frame(width: 24, height: 24)
                        .rotationEffect(isAnimating ? .degrees(-15) : .zero)
                        .scaleEffect(isAnimating ? 1.5 : 1.0)
                        .animation(.bouncy(extraBounce: 0.2), value: isAnimating)
                        .animation(.easeInOut(duration: 0.3), value: isHighlighted)
                }
        }
        .buttonStyle(ScaleButtonStyle())
        .maybeTooltip(
            isMore: isMore,
            tooltip: tooltip,
            tooltipAccentColor: tooltipAccentColor,
            tooltipDismissedAction: tooltipDismissedAction
        )
    }

    // MARK: - Helpers

    private func handleTap() {
        action()
        guard !isHighlighted, shouldAnimateOnTap else { return }
        isAnimating = true
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
            isAnimating = false
        }
    }

    private var labelFont: TypographyV1 = .init(
        name: "monospace Small",
        size: 10,
        style: .caption,
        weight: .inputSans,
        kerning: -0.8,
        lineHeight: 14
    )
}

private extension View {
    func maybeTooltip(
        isMore: Bool = false,
        tooltip: Tooltip? = nil,
        tooltipAccentColor: Color? = nil,
        tooltipDismissedAction: (() -> Void)? = nil
    ) -> some View {
        modifier(
            if: isMore,
            then: { view in
                view.modifier(MoreButtonTooltipModifier(
                    showTooltip: Binding(get: { tooltip != nil }, set: { _ in }),
                    tooltip: tooltip,
                    accentColor: tooltipAccentColor ?? .accentColor,
                    buttonWidth: 48,
                    onDismiss: {
                        tooltipDismissedAction?()
                    }
                ))
            }
        )
    }
}
