import SwiftUI

// MARK: - Animated Button Style

struct ZXButtonStyle: ButtonStyle {
    let branded: Bool

    init(branded: Bool = false) {
        self.branded = branded
    }

    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .scaleEffect(configuration.isPressed ? 0.96 : 1.0)
            .opacity(configuration.isPressed ? 0.85 : 1.0)
            .animation(.easeOut(duration: 0.15), value: configuration.isPressed)
            .sensoryFeedback(.impact(weight: .light), trigger: configuration.isPressed)
    }
}

// MARK: - Scale press modifier (quick apply)

struct ZXPressModifier: ViewModifier {
    @State private var pressed = false

    func body(content: Content) -> some View {
        content
            .scaleEffect(pressed ? 0.96 : 1.0)
            .opacity(pressed ? 0.8 : 1.0)
            .animation(.easeOut(duration: 0.12), value: pressed)
            .onLongPressGesture(minimumDuration: .infinity, pressing: { pressing in
                pressed = pressing
            }, perform: {})
            .sensoryFeedback(.impact(weight: .light), trigger: pressed)
    }
}

extension View {
    func zxPressable() -> some View {
        modifier(ZXPressModifier())
    }
}

// MARK: - Page transition modifier

struct ZXPageTransition: ViewModifier {
    let edge: Edge

    func body(content: Content) -> some View {
        content
            .transition(
                .move(edge: edge)
                .combined(with: .opacity)
            )
    }
}

extension View {
    func zxPageTransition(from edge: Edge = .trailing) -> some View {
        modifier(ZXPageTransition(edge: edge))
    }
}

// MARK: - AI Thinking overlay

struct ZXThinkingOverlay: View {
    let message: String

    init(_ message: String = "AI 正在分析你的回答…") {
        self.message = message
    }

    @Environment(\.accessibilityReduceMotion) private var reduceMotion
    @State private var show = false

    var body: some View {
        ZStack {
            Color.black.opacity(0.4).ignoresSafeArea()

            VStack(spacing: 20) {
                ZStack {
                    Circle()
                        .fill(RadialGradient(
                            colors: [Color(hex: "#7C6EFA", opacity: 0.3), .clear],
                            center: .center, startRadius: 8, endRadius: 32
                        ))
                        .frame(width: 64, height: 64)
                        .scaleEffect(show && !reduceMotion ? 1.3 : 1.0)
                        .animation(reduceMotion ? nil : .easeInOut(duration: 1.5).repeatForever(autoreverses: true), value: show)

                    Image(systemName: "brain.head.profile")
                        .font(.system(size: 28))
                        .foregroundColor(.white.opacity(0.9))
                }

                VStack(spacing: 12) {
                    Text(message)
                        .font(.system(size: 15, weight: .semibold))
                        .foregroundColor(.white)
                    if !reduceMotion { ZXDotLoader(color: .white) }
                    else { Text("处理中…").font(.system(size: 12)).foregroundColor(.white.opacity(0.7)) }
                }
            }
            .padding(32)
            .background(
                RoundedRectangle(cornerRadius: 24)
                    .fill(.ultraThinMaterial)
            )
        }
        .onAppear { show = true }
    }
}

// MARK: - Celebration / Confetti effect

struct ZXCelebrationView: View {
    let title: String
    let subtitle: String
    let onDismiss: () -> Void

    @Environment(\.accessibilityReduceMotion) private var reduceMotion
    @State private var particles: [ConfettiParticle] = []
    @State private var showContent = false

    var body: some View {
        ZStack {
            Color.black.opacity(0.5).ignoresSafeArea()
                .onTapGesture { dismiss() }

            if !reduceMotion {
                ForEach(particles) { p in
                    Circle()
                        .fill(p.color)
                        .frame(width: p.size, height: p.size)
                        .position(x: p.x, y: p.y)
                        .opacity(p.opacity)
                        .scaleEffect(p.scale)
                }
            }

            // Content card
            VStack(spacing: 20) {
                ZStack {
                    Circle()
                        .fill(
                            LinearGradient(
                                colors: [Color(hex: "#7C6EFA"), Color(hex: "#F97316")],
                                startPoint: .topLeading, endPoint: .bottomTrailing
                            )
                        )
                        .frame(width: 80, height: 80)
                    Image(systemName: "sparkles")
                        .font(.system(size: 36))
                        .foregroundColor(.white)
                }
                .scaleEffect(showContent && !reduceMotion ? 1 : 1)
                .animation(reduceMotion ? nil : .spring(response: 0.5, dampingFraction: 0.6).delay(0.2), value: showContent)

                VStack(spacing: 6) {
                    Text(title)
                        .font(.system(size: 22, weight: .heavy))
                        .foregroundColor(.white)
                    Text(subtitle)
                        .font(.system(size: 14))
                        .foregroundColor(Color(hex: "#F0F0FF", opacity: 0.6))
                }
                .opacity(reduceMotion ? 1 : (showContent ? 1 : 0))
                .offset(y: reduceMotion ? 0 : (showContent ? 0 : 20))

                Button(action: dismiss) {
                    Text("继续学习")
                        .font(.system(size: 16, weight: .bold))
                        .foregroundColor(.white)
                        .frame(maxWidth: .infinity)
                        .frame(height: 52)
                        .background(
                            LinearGradient(
                                colors: [Color(hex: "#7C6EFA"), Color(hex: "#F97316")],
                                startPoint: .topLeading, endPoint: .bottomTrailing
                            )
                        )
                        .clipShape(RoundedRectangle(cornerRadius: 16))
                }
                .opacity(reduceMotion ? 1 : (showContent ? 1 : 0))
            }
            .padding(28)
            .background(
                RoundedRectangle(cornerRadius: 24)
                    .fill(.ultraThinMaterial)
            )
            .padding(.horizontal, 20)
        }
        .onAppear {
            showContent = true
            if !reduceMotion { launchConfetti() }
        }
    }

    private func dismiss() {
        withAnimation(.easeOut(duration: 0.25)) { showContent = false }
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
            onDismiss()
        }
    }

    private func launchConfetti() {
        let colors: [Color] = [Color(hex: "#7C6EFA"), Color(hex: "#F97316"),
                                Color(hex: "#A78BFA"), Color(hex: "#34D399"),
                                Color(hex: "#F59E0B"), Color(hex: "#4ECDC4")]
        var ps: [ConfettiParticle] = []
        for i in 0..<36 {
            let delay = Double(i) * 0.015
            let x = CGFloat.random(in: 0...UIScreen.main.bounds.width)
            let endY = CGFloat.random(in: 80...UIScreen.main.bounds.height * 0.7)
            let size = CGFloat.random(in: 4...10)
            let color = colors.randomElement()!
            ps.append(ConfettiParticle(
                id: UUID(), color: color, size: size,
                x: x, y: -30, targetY: endY,
                scale: 1, opacity: 1, delay: delay
            ))
        }
        particles = ps

        for p in particles {
            withAnimation(.spring(response: 0.8, dampingFraction: 0.6).delay(p.delay)) {
                if let idx = particles.firstIndex(where: { $0.id == p.id }) {
                    particles[idx].y = p.targetY
                    particles[idx].opacity = 0.4
                    particles[idx].scale = 0.3
                }
            }
        }
    }
}

private struct ConfettiParticle: Identifiable {
    let id: UUID
    let color: Color
    let size: CGFloat
    var x: CGFloat
    var y: CGFloat
    let targetY: CGFloat
    var scale: CGFloat
    var opacity: Double
    let delay: Double
}

// MARK: - AI Analysis progress view

struct ZXAIAnalysisProgress: View {
    let steps: [String]
    @Environment(\.accessibilityReduceMotion) private var reduceMotion
    @State private var currentStep = 0
    @State private var progress: CGFloat = 0

    var body: some View {
        VStack(spacing: 24) {
            ZStack {
                if reduceMotion {
                    ProgressView().scaleEffect(1.5)
                } else {
                    ZXLoadingView(size: 48, lineWidth: 3)
                }
            }

            VStack(spacing: 4) {
                Text("AI 分析中…")
                    .font(.system(size: 17, weight: .bold))
                    .foregroundColor(Color.zxF0)
                Text(steps[safe: currentStep] ?? steps.last ?? "")
                    .font(.system(size: 13))
                    .foregroundColor(Color.zxF04)
            }

            GeometryReader { g in
                ZStack(alignment: .leading) {
                    RoundedRectangle(cornerRadius: 3)
                        .fill(Color.zxFill008)
                        .frame(height: 6)
                    RoundedRectangle(cornerRadius: 3)
                        .fill(ZXGradient.progressBar)
                        .frame(width: g.size.width * progress, height: 6)
                        .animation(.easeInOut(duration: 0.6), value: progress)
                }
            }
            .frame(height: 6)
            .padding(.horizontal, 40)
        }
        .padding(28)
        .background(
            RoundedRectangle(cornerRadius: 20)
                .fill(.ultraThinMaterial)
        )
        .padding(.horizontal, 40)
        .onAppear {
            if reduceMotion {
                currentStep = steps.count - 1
                progress = 1.0
            } else {
                var delay: TimeInterval = 0.8
                for i in 0..<steps.count {
                    DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
                        currentStep = i
                        progress = CGFloat(i + 1) / CGFloat(steps.count)
                    }
                    delay += 1.2
                }
            }
        }
    }
}

private extension Array {
    subscript(safe index: Int) -> Element? {
        indices.contains(index) ? self[index] : nil
    }
}
