import SwiftUI

public struct ClipListItemMoreButtonTooltipModifier: ViewModifier {
    @Binding var showTooltip: Bool
    @State var isShowingTooltip = false
    @State private var shadowRadius: CGFloat = 4
    @State private var activeTooltip: Tooltip?
    @State private var tooltipWidth: CGFloat = 0
    let accentColor: Color
    let buttonWidth: CGFloat
    let tooltip: Tooltip?
    let configuration: Tooltip.Configuration
    let onDismiss: () -> Void

    public init(
        showTooltip: Binding<Bool>,
        tooltip: Tooltip?,
        accentColor: Color,
        buttonWidth: CGFloat,
        onDismiss: @escaping () -> Void
    ) {
        self._showTooltip = showTooltip
        self.tooltip = tooltip
        self.accentColor = accentColor
        self.buttonWidth = buttonWidth
        self.configuration = .moreButtonOnClipInClipList
        self.onDismiss = onDismiss
    }

    var tooltipPosition: CGPoint {
        return tooltipPosition(
            in: buttonWidth,
            for: tooltipWidth,
            anchor: configuration.anchor,
            spacing: configuration.spacing
        )
    }

    public func body(content: Content) -> some View {
        content
            .background(
                Circle().frame(width: buttonWidth, height: buttonWidth)
                    .foregroundColor(Color.SemanticV1.textInvert)
                    .shadow(color: isShowingTooltip ? accentColor : .clear, radius: isShowingTooltip ? shadowRadius : 0)
                    .opacity(isShowingTooltip ? 1 : 0)
            )
            .overlay {
                if isShowingTooltip, let tooltip = activeTooltip {
                    TooltipView(
                        tooltip: tooltip,
                        maxWidth: configuration.maxWidth,
                        accentColor: accentColor,
                        onButtonTap: {}
                    )
                    .onGeometryChange(for: CGSize.self) { proxy in proxy.size } action: { size in
                        tooltipWidth = size.width
                    }
                    .transition(
                        .asymmetric(
                            insertion: .scale(scale: 0.95)
                                .combined(with: .opacity),
                            removal: .scale(scale: 0.95)
                                .combined(with: .opacity)
                        )
                    )
                    .offset(
                        x: tooltipPosition.x,
                        y: tooltipPosition.y
                    )
                    .zIndex(.infinity)
                }
            }
            .onChange(of: showTooltip) { _, isShowing in
                if isShowing {
                    activeTooltip = tooltip
                    withAnimation(.easeInOut(duration: 0.3)) {
                        isShowingTooltip = true
                    }
                    withAnimation(.easeInOut(duration: 1.5).repeatForever(autoreverses: true)) {
                        shadowRadius = configuration.anchorObjectShadowRadius
                    }
                } else {
                    withAnimation(.easeInOut(duration: 0.2)) {
                        isShowingTooltip = false
                        shadowRadius = 0
                    }
                    activeTooltip = nil
                }
            }
    }

    private func tooltipPosition(
        in buttonSize: CGFloat,
        for tooltipWidth: CGFloat,
        anchor: Tooltip.Anchor,
        spacing: CGFloat
    ) -> CGPoint {
        switch anchor {
        case .right(let offset):
            return CGPoint(
                x: -(tooltipWidth / 2 + buttonSize / 2 + spacing),
                y: -offset + buttonSize / 2
            )

        case .left(let offset):
            return CGPoint(
                x: tooltipWidth / 2 + spacing + buttonSize / 2,
                y: -offset + buttonSize / 2
            )

        default:
            return CGPoint(x: 0, y: 0)
        }
    }
}
