import SwiftUI

// MARK: - TourOverlayView

/// Full-screen overlay that renders the spotlight cutout and tour card.
/// Inserted by the `tourPresenter()` modifier.
struct TourOverlayView: View {

    let coordinator: TourCoordinator
    /// Frames of all registered tour targets in the overlay's coordinate space.
    let targetFrames: [TourTargetID: CGRect]

    // MARK: Computed

    private var spotlightFrame: CGRect {
        guard let target = coordinator.currentStep?.target else { return .zero }
        return targetFrames[target] ?? .zero
    }

    private var hasSpotlight: Bool { spotlightFrame != .zero }

    private var paddedSpotlight: CGRect {
        guard hasSpotlight, let step = coordinator.currentStep else { return .zero }
        return spotlightFrame.insetBy(dx: -step.spotlightPadding, dy: -step.spotlightPadding)
    }

    private var cornerRadius: CGFloat {
        coordinator.currentStep?.spotlightCornerRadius ?? 18
    }

    // MARK: Body

    var body: some View {
        if coordinator.isActive {
            GeometryReader { geo in
                ZStack(alignment: .top) {
                    // ── Backdrop ───────────────────────────────────────────────
                    backdrop(in: geo)

                    // ── Spotlight glow ring ────────────────────────────────────
                    if hasSpotlight {
                        spotlightGlow
                    }

                    // ── Tour card ──────────────────────────────────────────────
                    tourCard(in: geo)
                }
            }
            .ignoresSafeArea()
            .transition(.opacity)
            .animation(.easeInOut(duration: 0.25), value: coordinator.isActive)
            // Success haptic at tour end is triggered by TourCardView step change
            .sensoryFeedback(.success, trigger: !coordinator.isActive)
        }
    }

    // MARK: Backdrop

    @ViewBuilder
    private func backdrop(in geo: GeometryProxy) -> some View {
        let fullRect = CGRect(origin: .zero, size: geo.size)

        if hasSpotlight {
            // Subtle dark tint — only slightly dims the non-spotlight area
            // so the user can still see and orient themselves in the UI
            SpotlightShape(spotlight: paddedSpotlight, cornerRadius: cornerRadius)
                .fill(Color.black.opacity(0.18), style: FillStyle(eoFill: true))
                .frame(width: fullRect.width, height: fullRect.height)
                .ignoresSafeArea()
                .animation(.spring(response: 0.45, dampingFraction: 0.85), value: paddedSpotlight)
        } else {
            // No spotlight: very subtle tint so the screen stays readable
            Color.black.opacity(0.15)
                .ignoresSafeArea()
        }
    }

    // MARK: Spotlight Glow

    private var spotlightGlow: some View {
        RoundedRectangle(cornerRadius: cornerRadius, style: .continuous)
            .strokeBorder(NahbarInsightStyle.accentCoral.opacity(0.6), lineWidth: 1.5)
            .shadow(color: NahbarInsightStyle.accentCoral.opacity(0.45), radius: 12)
            .frame(width: paddedSpotlight.width, height: paddedSpotlight.height)
            .position(x: paddedSpotlight.midX, y: paddedSpotlight.midY)
            .animation(.spring(response: 0.45, dampingFraction: 0.85), value: paddedSpotlight)
    }

    // MARK: Tour Card

    @ViewBuilder
    private func tourCard(in geo: GeometryProxy) -> some View {
        let cardWidth: CGFloat = min(geo.size.width - 48, 380)
        let cardY = cardYPosition(in: geo)

        TourCardView(
            coordinator: coordinator,
            totalSteps: coordinator.stepCount,
            currentIndex: coordinator.currentStepIndex
        )
        .frame(width: cardWidth)
        .position(x: geo.size.width / 2, y: cardY)
        .animation(.spring(response: 0.45, dampingFraction: 0.85), value: coordinator.currentStepIndex)
    }

    private func cardYPosition(in geo: GeometryProxy) -> CGFloat {
        let screenHeight = geo.size.height
        let cardHeight: CGFloat = 260   // Approximate card height
        let margin: CGFloat = 24
        let safeTop = geo.safeAreaInsets.top
        let safeBottom = geo.safeAreaInsets.bottom

        guard hasSpotlight else {
            // No spotlight → center the card
            return screenHeight / 2
        }

        let step = coordinator.currentStep
        let position = step?.preferredCardPosition ?? .auto

        // Space above and below spotlight
        let spaceAbove = paddedSpotlight.minY - safeTop - margin
        let spaceBelow = screenHeight - paddedSpotlight.maxY - safeBottom - margin

        switch position {
        case .above:
            return paddedSpotlight.minY - cardHeight / 2 - margin
        case .below:
            return paddedSpotlight.maxY + cardHeight / 2 + margin
        case .center:
            return screenHeight / 2
        case .auto:
            if spaceBelow >= cardHeight {
                return paddedSpotlight.maxY + cardHeight / 2 + margin
            } else if spaceAbove >= cardHeight {
                return paddedSpotlight.minY - cardHeight / 2 - margin
            } else {
                return screenHeight / 2
            }
        }
    }
}
