//
//  CelebrationAnimations.swift
//  Reflect
//
//  Full-view celebration animations that play after voting.
//

import SwiftUI

// MARK: - Animation Type Enum

enum CelebrationAnimationType: String, CaseIterable, Identifiable {
    case confettiCannon = "Confetti"
    case vortexCheckmark = "Vortex"
    case explosionReveal = "Explosion"
    case flipReveal = "Flip"
    case shatterReform = "Shatter"
    case pulseWave = "Pulse Wave"
    case fireworks = "Fireworks"
    case morphBlob = "Morph"
    case zoomTunnel = "Tunnel"
    case gravityDrop = "Gravity"

    var id: String { rawValue }

    /// Int index for AppStorage persistence (enum uses String raw values)
    var index: Int {
        Self.allCases.firstIndex(of: self) ?? 0
    }

    /// Restore from persisted Int index
    static func fromIndex(_ index: Int) -> CelebrationAnimationType {
        guard index >= 0, index < allCases.count else { return .confettiCannon }
        return allCases[index]
    }

    var icon: String {
        switch self {
        case .confettiCannon: return "party.popper.fill"
        case .vortexCheckmark: return "tornado"
        case .explosionReveal: return "sparkles"
        case .flipReveal: return "rectangle.portrait.rotate"
        case .shatterReform: return "square.grid.3x3"
        case .pulseWave: return "dot.radiowaves.left.and.right"
        case .fireworks: return "fireworks"
        case .morphBlob: return "drop.fill"
        case .zoomTunnel: return "circle.dashed"
        case .gravityDrop: return "arrow.down.to.line"
        }
    }

    var description: String {
        switch self {
        case .confettiCannon: return "Party confetti"
        case .vortexCheckmark: return "Sucked into center"
        case .explosionReveal: return "Explodes outward"
        case .flipReveal: return "3D card flip"
        case .shatterReform: return "Shatters & reforms"
        case .pulseWave: return "Expanding waves"
        case .fireworks: return "Celebration burst"
        case .morphBlob: return "Liquid transform"
        case .zoomTunnel: return "Warp speed zoom"
        case .gravityDrop: return "Falls with bounce"
        }
    }

    var accentColor: Color {
        switch self {
        case .confettiCannon: return .pink
        case .vortexCheckmark: return .purple
        case .explosionReveal: return .orange
        case .flipReveal: return .blue
        case .shatterReform: return .red
        case .pulseWave: return .green
        case .fireworks: return .yellow
        case .morphBlob: return .cyan
        case .zoomTunnel: return .indigo
        case .gravityDrop: return .mint
        }
    }

    var duration: Double {
        switch self {
        case .confettiCannon: return 2.2
        case .vortexCheckmark: return 2.0
        case .explosionReveal: return 1.8
        case .flipReveal: return 1.5
        case .shatterReform: return 2.2
        case .pulseWave: return 1.6
        case .fireworks: return 2.5
        case .morphBlob: return 2.0
        case .zoomTunnel: return 1.8
        case .gravityDrop: return 2.0
        }
    }

    static var random: CelebrationAnimationType {
        allCases.randomElement() ?? .confettiCannon
    }
}

// MARK: - Celebration Overlay View

struct CelebrationOverlayView: View {
    let animationType: CelebrationAnimationType
    let mood: Mood
    let onComplete: () -> Void

    @State private var hasAppeared = false

    var body: some View {
        ZStack {
            if hasAppeared {
                animationView
            }
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .onAppear {
            hasAppeared = true
            Task { @MainActor in
                try? await Task.sleep(for: .seconds(animationType.duration))
                onComplete()
            }
        }
    }

    @ViewBuilder
    private var animationView: some View {
        switch animationType {
        case .vortexCheckmark:
            VortexCheckmarkAnimation(mood: mood)
        case .explosionReveal:
            ExplosionRevealAnimation(mood: mood)
        case .flipReveal:
            FlipRevealAnimation(mood: mood)
        case .shatterReform:
            ShatterReformAnimation(mood: mood)
        case .pulseWave:
            PulseWaveAnimation(mood: mood)
        case .fireworks:
            FireworksAnimation(mood: mood)
        case .confettiCannon:
            ConfettiCannonAnimation(mood: mood)
        case .morphBlob:
            MorphBlobAnimation(mood: mood)
        case .zoomTunnel:
            ZoomTunnelAnimation(mood: mood)
        case .gravityDrop:
            GravityDropAnimation(mood: mood)
        }
    }
}

// MARK: - Animation 1: Vortex Checkmark

struct VortexCheckmarkAnimation: View {
    let mood: Mood

    @State private var spiralRotation: Double = 0
    @State private var checkmarkScale: CGFloat = 0
    @State private var checkmarkOpacity: Double = 0
    @State private var ringScale: CGFloat = 0.5
    @State private var ringOpacity: Double = 0

    var body: some View {
        ZStack {
            ForEach(0..<8, id: \.self) { i in
                Circle()
                    .stroke(mood.color.opacity(0.3), lineWidth: 2)
                    .frame(width: CGFloat(30 + i * 25), height: CGFloat(30 + i * 25))
                    .rotationEffect(.degrees(spiralRotation + Double(i * 15)))
            }

            Circle()
                .stroke(mood.color, lineWidth: 4)
                .frame(width: 100, height: 100)
                .scaleEffect(ringScale)
                .opacity(ringOpacity)

            Image(systemName: "checkmark")
                .font(.system(size: 50, weight: .bold))
                .foregroundColor(mood.color)
                .scaleEffect(checkmarkScale)
                .opacity(checkmarkOpacity)
        }
        .onAppear {
            withAnimation(.easeOut(duration: 0.5)) { spiralRotation = 180 }
            withAnimation(.easeOut(duration: 0.3).delay(0.3)) { ringScale = 1.2; ringOpacity = 1 }
            withAnimation(.easeIn(duration: 0.2).delay(0.6)) { ringScale = 1.0 }
            withAnimation(.spring(response: 0.4, dampingFraction: 0.5).delay(0.5)) { checkmarkScale = 1.2; checkmarkOpacity = 1 }
            withAnimation(.spring(response: 0.2, dampingFraction: 0.6).delay(0.7)) { checkmarkScale = 1.0 }
            withAnimation(.easeOut(duration: 0.3).delay(1.5)) { checkmarkOpacity = 0; ringOpacity = 0 }
        }
    }
}

// MARK: - Animation 2: Explosion Reveal

struct ExplosionRevealAnimation: View {
    let mood: Mood

    @State private var particles: [ExplosionParticle] = []
    @State private var checkmarkOffset: CGFloat = -200
    @State private var checkmarkScale: CGFloat = 1.5
    @State private var checkmarkOpacity: Double = 0
    @State private var glowOpacity: Double = 0

    struct ExplosionParticle: Identifiable {
        let id = UUID()
        let angle: Double
        let distance: CGFloat
        let size: CGFloat
        let color: Color
        var offset: CGFloat = 0
        var opacity: Double = 1
        var rotation: Double = 0
    }

    var body: some View {
        ZStack {
            ForEach(particles) { particle in
                RoundedRectangle(cornerRadius: 4)
                    .fill(particle.color)
                    .frame(width: particle.size, height: particle.size)
                    .rotationEffect(.degrees(particle.rotation))
                    .offset(x: cos(particle.angle) * particle.offset, y: sin(particle.angle) * particle.offset)
                    .opacity(particle.opacity)
            }

            Circle()
                .fill(RadialGradient(colors: [mood.color.opacity(0.5), .clear], center: .center, startRadius: 0, endRadius: 100))
                .frame(width: 200, height: 200)
                .opacity(glowOpacity)

            Image(systemName: "checkmark.circle.fill")
                .font(.system(size: 70))
                .foregroundColor(mood.color)
                .offset(y: checkmarkOffset)
                .scaleEffect(checkmarkScale)
                .opacity(checkmarkOpacity)
        }
        .onAppear {
            for i in 0..<20 {
                let angle = Double(i) * (2 * .pi / 20) + Double.random(in: -0.2...0.2)
                particles.append(ExplosionParticle(angle: angle, distance: CGFloat.random(in: 100...180), size: CGFloat.random(in: 8...20), color: [mood.color, mood.color.opacity(0.7), .white, .orange][i % 4]))
            }
            withAnimation(.easeOut(duration: 0.6)) { for i in particles.indices { particles[i].offset = particles[i].distance; particles[i].rotation = Double.random(in: 0...360) } }
            withAnimation(.easeOut(duration: 0.4).delay(0.4)) { for i in particles.indices { particles[i].opacity = 0 } }
            withAnimation(.easeInOut(duration: 0.3).delay(0.2)) { glowOpacity = 1 }
            withAnimation(.easeOut(duration: 0.5).delay(0.6)) { glowOpacity = 0 }
            withAnimation(.spring(response: 0.5, dampingFraction: 0.6).delay(0.3)) { checkmarkOffset = 0; checkmarkScale = 1.0; checkmarkOpacity = 1 }
            withAnimation(.easeOut(duration: 0.3).delay(1.4)) { checkmarkOpacity = 0 }
        }
    }
}

// MARK: - Animation 3: Flip Reveal

struct FlipRevealAnimation: View {
    let mood: Mood

    @State private var showBack = false
    @State private var checkmarkScale: CGFloat = 0.5
    @State private var shimmerOffset: CGFloat = -200

    var body: some View {
        GeometryReader { geo in
            ZStack {
                RoundedRectangle(cornerRadius: 20)
                    .fill(LinearGradient(colors: [mood.color, mood.color.opacity(0.7)], startPoint: .topLeading, endPoint: .bottomTrailing))
                    .overlay(
                        Rectangle()
                            .fill(LinearGradient(colors: [.clear, .white.opacity(0.4), .clear], startPoint: .leading, endPoint: .trailing))
                            .frame(width: 60)
                            .offset(x: shimmerOffset)
                            .blur(radius: 5)
                    )
                    .clipShape(RoundedRectangle(cornerRadius: 20))
                    .overlay(
                        VStack(spacing: 16) {
                            Image(systemName: "checkmark.circle.fill")
                                .font(.system(size: 60))
                                .foregroundColor(.white)
                                .scaleEffect(checkmarkScale)
                            Text("Logged!")
                                .font(.title2.weight(.bold))
                                .foregroundColor(.white)
                        }
                    )
                    .opacity(showBack ? 1 : 0)
            }
            .frame(width: geo.size.width, height: geo.size.height)
        }
        .onAppear {
            withAnimation(.easeInOut(duration: 0.3).delay(0.2)) { showBack = true }
            withAnimation(.spring(response: 0.4, dampingFraction: 0.6).delay(0.4)) { checkmarkScale = 1.1 }
            withAnimation(.spring(response: 0.2, dampingFraction: 0.7).delay(0.6)) { checkmarkScale = 1.0 }
            withAnimation(.easeInOut(duration: 0.8).delay(0.5)) { shimmerOffset = 200 }
        }
    }
}

// MARK: - Animation 4: Shatter Reform

struct ShatterReformAnimation: View {
    let mood: Mood

    @State private var shardOffsets: [CGSize] = []
    @State private var shardRotations: [Double] = []
    @State private var shardOpacities: [Double] = []
    @State private var phase: AnimationPhase = .initial
    @State private var checkmarkOpacity: Double = 0

    enum AnimationPhase { case initial, shatter, reform, complete }

    private let shardCount = 12

    var body: some View {
        ZStack {
            // Shards that explode outward
            ForEach(0..<shardCount, id: \.self) { i in
                Rectangle()
                    .fill(mood.color.opacity(Double.random(in: 0.5...1.0)))
                    .frame(width: 20, height: 20)
                    .rotationEffect(.degrees(shardRotations.indices.contains(i) ? shardRotations[i] : 0))
                    .offset(shardOffsets.indices.contains(i) ? shardOffsets[i] : .zero)
                    .opacity(shardOpacities.indices.contains(i) ? shardOpacities[i] : 1)
            }

            // Checkmark
            Image(systemName: "checkmark")
                .font(.system(size: 60, weight: .bold))
                .foregroundColor(mood.color)
                .opacity(checkmarkOpacity)
        }
        .onAppear {
            // Initialize arrays
            shardOffsets = Array(repeating: .zero, count: shardCount)
            shardRotations = Array(repeating: 0, count: shardCount)
            shardOpacities = Array(repeating: 1, count: shardCount)

            // Phase 1: Explode outward
            withAnimation(.easeOut(duration: 0.5)) {
                for i in 0..<shardCount {
                    let angle = Double(i) * (2 * .pi / Double(shardCount))
                    let distance: CGFloat = CGFloat.random(in: 80...140)
                    shardOffsets[i] = CGSize(
                        width: cos(angle) * distance,
                        height: sin(angle) * distance
                    )
                    shardRotations[i] = Double.random(in: -180...180)
                }
            }

            // Phase 2: Converge to center and fade
            Task { @MainActor in
                try? await Task.sleep(for: .seconds(0.6))
                phase = .reform
                withAnimation(.easeInOut(duration: 0.5)) {
                    for i in 0..<shardCount {
                        shardOffsets[i] = .zero
                        shardRotations[i] = 0
                        shardOpacities[i] = 0
                    }
                }
            }

            // Phase 3: Show checkmark
            Task { @MainActor in
                try? await Task.sleep(for: .seconds(1.1))
                withAnimation(.spring(response: 0.3, dampingFraction: 0.6)) {
                    checkmarkOpacity = 1
                }
            }

            // Phase 4: Fade out
            Task { @MainActor in
                try? await Task.sleep(for: .seconds(1.8))
                withAnimation(.easeOut(duration: 0.3)) {
                    checkmarkOpacity = 0
                }
            }
        }
    }
}

// MARK: - Animation 5: Pulse Wave

struct PulseWaveAnimation: View {
    let mood: Mood

    @State private var wave1Scale: CGFloat = 0.1
    @State private var wave1Opacity: Double = 1
    @State private var wave2Scale: CGFloat = 0.1
    @State private var wave2Opacity: Double = 1
    @State private var wave3Scale: CGFloat = 0.1
    @State private var wave3Opacity: Double = 1
    @State private var checkmarkScale: CGFloat = 3.0
    @State private var checkmarkOpacity: Double = 0
    @State private var stampRotation: Double = -15

    var body: some View {
        ZStack {
            Circle().stroke(mood.color, lineWidth: 8).scaleEffect(wave1Scale).opacity(wave1Opacity)
            Circle().stroke(mood.color.opacity(0.7), lineWidth: 6).scaleEffect(wave2Scale).opacity(wave2Opacity)
            Circle().stroke(mood.color.opacity(0.4), lineWidth: 4).scaleEffect(wave3Scale).opacity(wave3Opacity)

            ZStack {
                Circle().fill(mood.color).frame(width: 80, height: 80)
                Image(systemName: "checkmark").font(.system(size: 40, weight: .bold)).foregroundColor(.white)
            }
            .scaleEffect(checkmarkScale)
            .opacity(checkmarkOpacity)
            .rotationEffect(.degrees(stampRotation))
        }
        .frame(width: 300, height: 300)
        .onAppear {
            withAnimation(.easeOut(duration: 0.6)) { wave1Scale = 1.5; wave1Opacity = 0 }
            withAnimation(.easeOut(duration: 0.6).delay(0.1)) { wave2Scale = 1.5; wave2Opacity = 0 }
            withAnimation(.easeOut(duration: 0.6).delay(0.2)) { wave3Scale = 1.5; wave3Opacity = 0 }
            withAnimation(.spring(response: 0.3, dampingFraction: 0.5).delay(0.2)) { checkmarkScale = 1.0; checkmarkOpacity = 1; stampRotation = 0 }
            withAnimation(.easeOut(duration: 0.3).delay(1.2)) { checkmarkOpacity = 0 }
        }
    }
}

// MARK: - Animation 6: Fireworks

struct FireworksAnimation: View {
    let mood: Mood

    @State private var bursts: [[FireworkParticle]] = []
    @State private var checkmarkScale: CGFloat = 0
    @State private var checkmarkOpacity: Double = 0

    struct FireworkParticle: Identifiable {
        let id = UUID()
        let angle: Double
        let color: Color
        var distance: CGFloat = 0
        var opacity: Double = 1
        var scale: CGFloat = 1
    }

    var body: some View {
        ZStack {
            ForEach(0..<bursts.count, id: \.self) { burstIndex in
                let offset = burstOffsets[burstIndex]
                ZStack {
                    ForEach(bursts[burstIndex]) { particle in
                        Circle()
                            .fill(particle.color)
                            .frame(width: 6, height: 6)
                            .scaleEffect(particle.scale)
                            .offset(
                                x: cos(particle.angle) * particle.distance,
                                y: sin(particle.angle) * particle.distance
                            )
                            .opacity(particle.opacity)
                    }
                }
                .offset(x: offset.x, y: offset.y)
            }

            Image(systemName: "checkmark.circle.fill")
                .font(.system(size: 60))
                .foregroundStyle(
                    LinearGradient(colors: [mood.color, mood.color.opacity(0.7)], startPoint: .top, endPoint: .bottom)
                )
                .scaleEffect(checkmarkScale)
                .opacity(checkmarkOpacity)
        }
        .onAppear {
            let colors: [Color] = [mood.color, .yellow, .orange, .pink, .white]

            for _ in 0..<4 {
                var particles: [FireworkParticle] = []
                for i in 0..<12 {
                    let angle = Double(i) * (2 * .pi / 12)
                    particles.append(FireworkParticle(angle: angle, color: colors.randomElement()!))
                }
                bursts.append(particles)
            }

            for burstIndex in 0..<4 {
                let delay = Double(burstIndex) * 0.15

                withAnimation(.easeOut(duration: 0.5).delay(delay)) {
                    for i in bursts[burstIndex].indices {
                        bursts[burstIndex][i].distance = CGFloat.random(in: 40...70)
                    }
                }

                withAnimation(.easeOut(duration: 0.4).delay(delay + 0.3)) {
                    for i in bursts[burstIndex].indices {
                        bursts[burstIndex][i].opacity = 0
                        bursts[burstIndex][i].scale = 0.3
                    }
                }
            }

            withAnimation(.spring(response: 0.4, dampingFraction: 0.6).delay(0.6)) {
                checkmarkScale = 1.1
                checkmarkOpacity = 1
            }
            withAnimation(.spring(response: 0.2, dampingFraction: 0.7).delay(0.8)) {
                checkmarkScale = 1.0
            }
            withAnimation(.easeOut(duration: 0.3).delay(2.0)) {
                checkmarkOpacity = 0
            }
        }
    }

    private var burstOffsets: [CGPoint] {
        [CGPoint(x: -60, y: -50), CGPoint(x: 70, y: -40), CGPoint(x: -50, y: 60), CGPoint(x: 60, y: 50)]
    }
}

// MARK: - Animation 7: Confetti Cannon

struct ConfettiCannonAnimation: View {
    let mood: Mood

    @State private var confetti: [ConfettiPiece] = []
    @State private var checkmarkScale: CGFloat = 0
    @State private var checkmarkOpacity: Double = 0
    @State private var glowScale: CGFloat = 0.5
    @State private var glowOpacity: Double = 0

    struct ConfettiPiece: Identifiable {
        let id = UUID()
        let color: Color
        let size: CGSize
        let xVelocity: CGFloat
        var yOffset: CGFloat = 200
        var rotation: Double = 0
        var opacity: Double = 1
    }

    var body: some View {
        ZStack {
            Circle()
                .fill(RadialGradient(colors: [mood.color.opacity(0.4), .clear], center: .center, startRadius: 0, endRadius: 80))
                .frame(width: 160, height: 160)
                .scaleEffect(glowScale)
                .opacity(glowOpacity)

            ForEach(confetti) { piece in
                RoundedRectangle(cornerRadius: 2)
                    .fill(piece.color)
                    .frame(width: piece.size.width, height: piece.size.height)
                    .rotationEffect(.degrees(piece.rotation))
                    .offset(x: piece.xVelocity, y: piece.yOffset)
                    .opacity(piece.opacity)
            }

            Image(systemName: "checkmark")
                .font(.system(size: 50, weight: .bold))
                .foregroundColor(mood.color)
                .scaleEffect(checkmarkScale)
                .opacity(checkmarkOpacity)
        }
        .onAppear {
            let colors: [Color] = [mood.color, .yellow, .pink, .orange, .cyan, .white]

            for i in 0..<30 {
                confetti.append(ConfettiPiece(
                    color: colors[i % colors.count],
                    size: CGSize(width: CGFloat.random(in: 6...12), height: CGFloat.random(in: 8...16)),
                    xVelocity: CGFloat.random(in: -120...120)
                ))
            }

            withAnimation(.easeOut(duration: 0.5)) {
                for i in confetti.indices {
                    confetti[i].yOffset = CGFloat.random(in: -150 ... -80)
                    confetti[i].rotation = Double.random(in: -180...180)
                }
            }

            withAnimation(.easeIn(duration: 1.0).delay(0.5)) {
                for i in confetti.indices {
                    confetti[i].yOffset = 200
                    confetti[i].rotation += Double.random(in: 180...540)
                }
            }

            withAnimation(.easeIn(duration: 0.3).delay(1.3)) {
                for i in confetti.indices { confetti[i].opacity = 0 }
            }

            withAnimation(.easeOut(duration: 0.3).delay(0.1)) { glowScale = 1.2; glowOpacity = 1 }
            withAnimation(.easeIn(duration: 0.4).delay(0.5)) { glowOpacity = 0 }

            withAnimation(.spring(response: 0.4, dampingFraction: 0.5).delay(0.3)) { checkmarkScale = 1.2; checkmarkOpacity = 1 }
            withAnimation(.spring(response: 0.2, dampingFraction: 0.6).delay(0.5)) { checkmarkScale = 1.0 }
            withAnimation(.easeOut(duration: 0.3).delay(1.8)) { checkmarkOpacity = 0 }
        }
    }
}

// MARK: - Animation 8: Morph Blob

struct MorphBlobAnimation: View {
    let mood: Mood

    @State private var blobScale: CGFloat = 0.3
    @State private var blobOffset1: CGSize = .zero
    @State private var blobOffset2: CGSize = .zero
    @State private var blobOffset3: CGSize = .zero
    @State private var checkmarkOpacity: Double = 0

    var body: some View {
        ZStack {
            ZStack {
                Circle()
                    .fill(mood.color.opacity(0.6))
                    .frame(width: 100, height: 100)
                    .offset(blobOffset1)
                    .blur(radius: 20)

                Circle()
                    .fill(mood.color.opacity(0.5))
                    .frame(width: 80, height: 80)
                    .offset(blobOffset2)
                    .blur(radius: 15)

                Circle()
                    .fill(mood.color.opacity(0.7))
                    .frame(width: 60, height: 60)
                    .offset(blobOffset3)
                    .blur(radius: 10)
            }
            .scaleEffect(blobScale)

            Image(systemName: "checkmark.circle.fill")
                .font(.system(size: 60))
                .foregroundColor(.white)
                .shadow(color: mood.color, radius: 10)
                .opacity(checkmarkOpacity)
        }
        .onAppear {
            withAnimation(.easeOut(duration: 0.4)) {
                blobScale = 1.5
                blobOffset1 = CGSize(width: -30, height: -40)
                blobOffset2 = CGSize(width: 40, height: 20)
                blobOffset3 = CGSize(width: -20, height: 50)
            }

            withAnimation(.easeInOut(duration: 0.5).delay(0.4)) {
                blobOffset1 = CGSize(width: 40, height: 30)
                blobOffset2 = CGSize(width: -30, height: -30)
                blobOffset3 = CGSize(width: 20, height: -40)
            }

            withAnimation(.easeInOut(duration: 0.4).delay(0.9)) {
                blobOffset1 = .zero
                blobOffset2 = .zero
                blobOffset3 = .zero
                blobScale = 0.8
            }

            withAnimation(.spring(response: 0.3, dampingFraction: 0.6).delay(1.2)) {
                checkmarkOpacity = 1
            }

            withAnimation(.easeOut(duration: 0.3).delay(1.7)) {
                checkmarkOpacity = 0
                blobScale = 0
            }
        }
    }
}

// MARK: - Animation 9: Zoom Tunnel

struct ZoomTunnelAnimation: View {
    let mood: Mood

    @State private var rings: [TunnelRing] = []
    @State private var checkmarkScale: CGFloat = 0
    @State private var checkmarkOpacity: Double = 0
    @State private var starburstRotation: Double = 0

    struct TunnelRing: Identifiable {
        let id = UUID()
        var scale: CGFloat
        var opacity: Double
    }

    var body: some View {
        ZStack {
            ForEach(rings) { ring in
                Circle()
                    .stroke(mood.color.opacity(0.5), lineWidth: 3)
                    .scaleEffect(ring.scale)
                    .opacity(ring.opacity)
            }

            ForEach(0..<8, id: \.self) { i in
                Rectangle()
                    .fill(LinearGradient(colors: [mood.color, .clear], startPoint: .center, endPoint: .trailing))
                    .frame(width: 150, height: 4)
                    .offset(x: 75)
                    .rotationEffect(.degrees(Double(i) * 45 + starburstRotation))
                    .opacity(checkmarkOpacity * 0.6)
            }

            Image(systemName: "checkmark.circle.fill")
                .font(.system(size: 70))
                .foregroundStyle(
                    LinearGradient(colors: [.white, mood.color], startPoint: .topLeading, endPoint: .bottomTrailing)
                )
                .shadow(color: mood.color, radius: 15)
                .scaleEffect(checkmarkScale)
                .opacity(checkmarkOpacity)
        }
        .onAppear {
            for i in 0..<6 {
                rings.append(TunnelRing(scale: CGFloat(3.0 - Double(i) * 0.4), opacity: 0))
            }

            for i in rings.indices {
                let delay = Double(i) * 0.1
                withAnimation(.easeIn(duration: 0.6).delay(delay)) {
                    rings[i].scale = 0.1
                    rings[i].opacity = 1
                }
                withAnimation(.easeIn(duration: 0.2).delay(delay + 0.4)) {
                    rings[i].opacity = 0
                }
            }

            withAnimation(.linear(duration: 2.0)) {
                starburstRotation = 45
            }

            withAnimation(.spring(response: 0.4, dampingFraction: 0.6).delay(0.5)) {
                checkmarkScale = 1.1
                checkmarkOpacity = 1
            }
            withAnimation(.spring(response: 0.2, dampingFraction: 0.7).delay(0.7)) {
                checkmarkScale = 1.0
            }
            withAnimation(.easeOut(duration: 0.3).delay(1.5)) {
                checkmarkOpacity = 0
            }
        }
    }
}

// MARK: - Animation 10: Gravity Drop

struct GravityDropAnimation: View {
    let mood: Mood

    @State private var checkmarkOffset: CGFloat = -200
    @State private var checkmarkRotation: Double = -30
    @State private var checkmarkScale: CGFloat = 0.5
    @State private var checkmarkOpacity: Double = 0
    @State private var impactRingScale: CGFloat = 0.3
    @State private var impactRingOpacity: Double = 0
    @State private var dustParticles: [DustParticle] = []

    struct DustParticle: Identifiable {
        let id = UUID()
        var xOffset: CGFloat
        var yOffset: CGFloat = 0
        var opacity: Double = 0
    }

    var body: some View {
        ZStack {
            Circle()
                .stroke(mood.color.opacity(0.5), lineWidth: 3)
                .scaleEffect(impactRingScale)
                .opacity(impactRingOpacity)
                .offset(y: 30)

            ForEach(dustParticles) { particle in
                Circle()
                    .fill(mood.color.opacity(0.4))
                    .frame(width: 8, height: 8)
                    .offset(x: particle.xOffset, y: particle.yOffset + 30)
                    .opacity(particle.opacity)
            }

            ZStack {
                Circle()
                    .fill(mood.color)
                    .frame(width: 80, height: 80)
                    .shadow(color: mood.color.opacity(0.5), radius: 10, y: 5)

                Image(systemName: "checkmark")
                    .font(.system(size: 40, weight: .bold))
                    .foregroundColor(.white)
            }
            .offset(y: checkmarkOffset)
            .rotationEffect(.degrees(checkmarkRotation))
            .scaleEffect(checkmarkScale)
            .opacity(checkmarkOpacity)
        }
        .onAppear {
            for i in 0..<8 {
                dustParticles.append(DustParticle(xOffset: CGFloat(i - 4) * 20))
            }

            withAnimation(.easeIn(duration: 0.1)) {
                checkmarkOpacity = 1
            }

            withAnimation(.easeIn(duration: 0.4)) {
                checkmarkOffset = 30
                checkmarkRotation = 10
                checkmarkScale = 1.0
            }

            withAnimation(.easeOut(duration: 0.2).delay(0.4)) {
                checkmarkOffset = -20
                checkmarkRotation = -5
            }

            withAnimation(.easeIn(duration: 0.15).delay(0.6)) {
                checkmarkOffset = 30
                checkmarkRotation = 3
            }

            withAnimation(.easeOut(duration: 0.1).delay(0.75)) {
                checkmarkOffset = 20
                checkmarkRotation = 0
            }

            withAnimation(.easeInOut(duration: 0.1).delay(0.85)) {
                checkmarkOffset = 30
            }

            withAnimation(.easeOut(duration: 0.4).delay(0.4)) {
                impactRingScale = 1.5
                impactRingOpacity = 0.8
            }
            withAnimation(.easeOut(duration: 0.3).delay(0.6)) {
                impactRingOpacity = 0
            }

            withAnimation(.easeOut(duration: 0.4).delay(0.4)) {
                for i in dustParticles.indices {
                    dustParticles[i].yOffset = CGFloat.random(in: -30 ... -10)
                    dustParticles[i].opacity = 0.8
                }
            }
            withAnimation(.easeIn(duration: 0.4).delay(0.7)) {
                for i in dustParticles.indices {
                    dustParticles[i].yOffset = 20
                    dustParticles[i].opacity = 0
                }
            }

            withAnimation(.easeOut(duration: 0.3).delay(1.6)) {
                checkmarkOpacity = 0
            }
        }
    }
}
