import SwiftUI

// MARK: - Animation Type Enum

enum TaskAnimationType: String, CaseIterable, Identifiable {
    case none = "None"
    case implode = "Implode"
    case firework = "Firework"
    case starburst = "Starburst"
    case ripple = "Ripple"

    var id: String { rawValue }

    var icon: String {
        switch self {
        case .none: return "minus.circle"
        case .implode: return "checkmark.circle"
        case .firework: return "sparkle"
        case .starburst: return "sun.max.fill"
        case .ripple: return "circle.circle"
        }
    }

    var description: String {
        switch self {
        case .none: return "No animation, instant move"
        case .implode: return "Sucks into center, becomes checkmark"
        case .firework: return "Explodes into colorful sparks"
        case .starburst: return "Radiating rays from checkmark"
        case .ripple: return "Checkmark with expanding rings"
        }
    }

    /// All celebration animations need extended timing for checkmark display
    var needsExtendedTiming: Bool {
        switch self {
        case .none: return false
        default: return true
        }
    }

    /// Selectable animation types (excludes "none" from picker in testing view)
    static var selectableCases: [TaskAnimationType] {
        allCases
    }
}

// MARK: - Animation Phase

enum AnimationPhase: Equatable {
    case idle
    case exiting
    case moving
    case entering
    case complete
}

// MARK: - Test Data Models

struct TestTask: Identifiable, Equatable {
    let id: String
    var title: String
    var description: String?
    var priority: TestPriority
    var frequency: String
    var dueDate: String

    enum TestPriority: String {
        case high = "High"
        case medium = "Medium"
        case low = "Low"

        var color: Color {
            switch self {
            case .high: return Color.appError
            case .medium: return Color.appAccent
            case .low: return Color.appPrimary
            }
        }
    }

    static let samples: [TestTask] = [
        TestTask(
            id: "1",
            title: "Clean Gutters",
            description: "Remove debris from all gutters",
            priority: .high,
            frequency: "Monthly",
            dueDate: "Dec 25"
        ),
        TestTask(
            id: "2",
            title: "Check HVAC Filters",
            description: "Replace if dirty",
            priority: .medium,
            frequency: "Quarterly",
            dueDate: "Dec 28"
        ),
        TestTask(
            id: "3",
            title: "Test Smoke Detectors",
            description: nil,
            priority: .high,
            frequency: "Monthly",
            dueDate: "Dec 30"
        )
    ]
}

struct TestColumn: Identifiable, Equatable {
    let id: String
    var name: String
    var displayName: String
    var color: Color
    var tasks: [TestTask]

    static var defaultColumns: [TestColumn] {
        [
            TestColumn(
                id: "todo",
                name: "To Do",
                displayName: "To Do",
                color: Color.appAccent,
                tasks: TestTask.samples
            ),
            TestColumn(
                id: "progress",
                name: "In Progress",
                displayName: "In Progress",
                color: Color.appPrimary,
                tasks: []
            ),
            TestColumn(
                id: "done",
                name: "Done",
                displayName: "Done",
                color: Color.appPrimary.opacity(0.6),
                tasks: []
            )
        ]
    }
}

// MARK: - Animation Chip

struct AnimationChip: View {
    let animation: TaskAnimationType
    let isSelected: Bool
    let onSelect: () -> Void

    var body: some View {
        Button(action: onSelect) {
            HStack(spacing: 6) {
                Image(systemName: animation.icon)
                    .font(.system(size: 12, weight: .semibold))
                Text(animation.rawValue)
                    .font(.system(size: 13, weight: .semibold, design: .rounded))
            }
            .foregroundColor(isSelected ? Color.appTextOnPrimary : Color.appTextPrimary)
            .padding(.horizontal, 12)
            .padding(.vertical, 8)
            .background(isSelected ? Color.appPrimary : Color.appBackgroundSecondary)
            .cornerRadius(AppRadius.md)
        }
        .buttonStyle(.plain)
    }
}

// MARK: - Animation View Modifiers

extension View {
    @ViewBuilder
    func taskAnimation(type: TaskAnimationType, phase: AnimationPhase) -> some View {
        switch type {
        case .none:
            self
        case .implode:
            self.implodeAnimation(phase: phase)
        case .firework:
            self.fireworkAnimation(phase: phase)
        case .starburst:
            self.starburstAnimation(phase: phase)
        case .ripple:
            self.rippleAnimation(phase: phase)
        }
    }
}

// MARK: - Animation Implementations

private extension View {

    // Implode - Sucks into center, becomes checkmark, disappears
    func implodeAnimation(phase: AnimationPhase) -> some View {
        ZStack {
            // Card content - shrinks and hides
            self
                .scaleEffect(phase == .idle ? 1.0 : 0.0)
                .opacity(phase == .idle ? 1.0 : 0.0)
                .animation(.easeIn(duration: 0.3), value: phase)

            // Checkmark overlay - NOT affected by the scale
            if phase == .complete {
                ImplodeCheckmarkView(phase: phase)
                    .allowsHitTesting(false)
            }
        }
    }

    // Firework - Explodes into colorful sparks with checkmark
    func fireworkAnimation(phase: AnimationPhase) -> some View {
        ZStack {
            // Card content - shrinks and hides
            self
                .scaleEffect(phase == .idle ? 1.0 : 0.0)
                .opacity(phase == .idle ? 1.0 : 0.0)
                .animation(.easeIn(duration: 0.25), value: phase)

            // Firework effect
            if phase == .complete {
                FireworkCheckmarkView()
                    .allowsHitTesting(false)
            }
        }
    }

    // Starburst - Radiating rays from checkmark
    func starburstAnimation(phase: AnimationPhase) -> some View {
        ZStack {
            // Card content - shrinks and hides
            self
                .scaleEffect(phase == .idle ? 1.0 : 0.0)
                .opacity(phase == .idle ? 1.0 : 0.0)
                .animation(.easeIn(duration: 0.3), value: phase)

            // Starburst effect
            if phase == .complete {
                StarburstCheckmarkView()
                    .allowsHitTesting(false)
            }
        }
    }

    // Ripple - Checkmark with expanding rings
    func rippleAnimation(phase: AnimationPhase) -> some View {
        ZStack {
            // Card content - shrinks and hides
            self
                .scaleEffect(phase == .idle ? 1.0 : 0.0)
                .opacity(phase == .idle ? 1.0 : 0.0)
                .animation(.easeIn(duration: 0.3), value: phase)

            // Ripple effect
            if phase == .complete {
                RippleCheckmarkView()
                    .allowsHitTesting(false)
            }
        }
    }
}

// MARK: - Implode Checkmark Animation View

struct ImplodeCheckmarkView: View {
    let phase: AnimationPhase

    @State private var checkmarkPhase: CheckmarkPhase = .appearing

    private enum CheckmarkPhase {
        case appearing
        case visible
        case disappearing
        case gone
    }

    var body: some View {
        ZStack {
            // Background circle that pulses
            Circle()
                .fill(Color.appPrimary.opacity(0.15))
                .frame(width: circleSize, height: circleSize)
                .scaleEffect(circleScale)

            // Checkmark circle
            Circle()
                .fill(Color.appPrimary)
                .frame(width: 56, height: 56)
                .scaleEffect(checkmarkCircleScale)
                .opacity(checkmarkOpacity)

            // Checkmark icon
            Image(systemName: "checkmark")
                .font(.system(size: 28, weight: .bold))
                .foregroundColor(.white)
                .scaleEffect(checkmarkIconScale)
                .opacity(checkmarkOpacity)
        }
        .onAppear {
            startAnimation()
        }
    }

    private var circleSize: CGFloat {
        switch checkmarkPhase {
        case .appearing: return 20
        case .visible: return 80
        case .disappearing, .gone: return 100
        }
    }

    private var circleScale: CGFloat {
        switch checkmarkPhase {
        case .appearing: return 0.2
        case .visible: return 1.0
        case .disappearing: return 1.3
        case .gone: return 0.0
        }
    }

    private var checkmarkCircleScale: CGFloat {
        switch checkmarkPhase {
        case .appearing: return 0.0
        case .visible: return 1.0
        case .disappearing: return 1.1
        case .gone: return 0.0
        }
    }

    private var checkmarkIconScale: CGFloat {
        switch checkmarkPhase {
        case .appearing: return 0.0
        case .visible: return 1.0
        case .disappearing: return 1.2
        case .gone: return 0.0
        }
    }

    private var checkmarkOpacity: Double {
        switch checkmarkPhase {
        case .appearing: return 0.0
        case .visible: return 1.0
        case .disappearing: return 0.8
        case .gone: return 0.0
        }
    }

    private func startAnimation() {
        // Phase 1: Appear with spring
        withAnimation(.spring(response: 0.4, dampingFraction: 0.6)) {
            checkmarkPhase = .visible
        }

        // Phase 2: Hold for 1.5 seconds then start disappearing
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
            withAnimation(.easeOut(duration: 0.4)) {
                checkmarkPhase = .disappearing
            }
        }

        // Phase 3: Fade out completely
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.9) {
            withAnimation(.easeOut(duration: 0.3)) {
                checkmarkPhase = .gone
            }
        }
    }
}

// MARK: - Standalone Completion Animation

// MARK: - Completion Animation Phase

enum CompletionAnimationPhase {
    case idle
    case imploding
    case checkmark
    case fading
    case done
}

/// A standalone view that can be overlaid on any content to show the implode-to-checkmark animation
struct TaskCompletionAnimation: View {
    @Binding var isAnimating: Bool
    var onComplete: (() -> Void)? = nil

    @State private var phase: CompletionAnimationPhase = .idle

    var body: some View {
        ZStack {
            if phase != .idle && phase != .done {
                // Radial lines sucking inward
                ForEach(0..<8, id: \.self) { index in
                    ImplodeLine(
                        angle: Double(index) * 45,
                        phase: phase
                    )
                }

                // Center checkmark
                if phase == .checkmark || phase == .fading {
                    ZStack {
                        // Glow effect
                        Circle()
                            .fill(
                                RadialGradient(
                                    colors: [Color.appPrimary.opacity(0.4), Color.clear],
                                    center: .center,
                                    startRadius: 20,
                                    endRadius: 60
                                )
                            )
                            .frame(width: 120, height: 120)
                            .scaleEffect(phase == .fading ? 1.5 : 1.0)
                            .opacity(phase == .fading ? 0 : 1)

                        // Main circle
                        Circle()
                            .fill(Color.appPrimary)
                            .frame(width: 60, height: 60)
                            .scaleEffect(checkmarkScale)
                            .opacity(phase == .fading ? 0 : 1)

                        // Checkmark
                        Image(systemName: "checkmark")
                            .font(.system(size: 30, weight: .bold))
                            .foregroundColor(.white)
                            .scaleEffect(checkmarkScale)
                            .opacity(phase == .fading ? 0 : 1)
                    }
                    .transition(.scale.combined(with: .opacity))
                }
            }
        }
        .onChange(of: isAnimating) { _, newValue in
            if newValue {
                startAnimation()
            }
        }
    }

    private var checkmarkScale: CGFloat {
        switch phase {
        case .checkmark: return 1.0
        case .fading: return 0.8
        default: return 0.0
        }
    }

    private func startAnimation() {
        phase = .idle

        // Phase 1: Implode lines animate inward
        withAnimation(.easeIn(duration: 0.3)) {
            phase = .imploding
        }

        // Phase 2: Show checkmark with spring
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
            withAnimation(.spring(response: 0.4, dampingFraction: 0.6)) {
                phase = .checkmark
            }
        }

        // Phase 3: Hold longer, then fade
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
            withAnimation(.easeOut(duration: 0.35)) {
                phase = .fading
            }
        }

        // Phase 4: Complete
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.85) {
            phase = .done
            isAnimating = false
            onComplete?()
        }
    }
}


/// Individual line that animates inward during implode
private struct ImplodeLine: View {
    let angle: Double
    let phase: CompletionAnimationPhase

    var body: some View {
        Rectangle()
            .fill(
                LinearGradient(
                    colors: [Color.appPrimary.opacity(0), Color.appPrimary],
                    startPoint: .leading,
                    endPoint: .trailing
                )
            )
            .frame(width: lineWidth, height: 3)
            .offset(x: offset)
            .rotationEffect(.degrees(angle))
            .opacity(lineOpacity)
            .animation(.easeIn(duration: 0.3), value: phase)
    }

    private var lineWidth: CGFloat {
        switch phase {
        case .idle: return 40
        case .imploding: return 0
        default: return 0
        }
    }

    private var offset: CGFloat {
        switch phase {
        case .idle: return 60
        case .imploding: return 0
        default: return 0
        }
    }

    private var lineOpacity: Double {
        switch phase {
        case .idle: return 1.0
        case .imploding: return 0.0
        default: return 0.0
        }
    }
}

// MARK: - Firework Checkmark Animation View

struct FireworkCheckmarkView: View {
    @State private var sparks: [FireworkSpark] = []
    @State private var checkmarkScale: CGFloat = 0
    @State private var checkmarkOpacity: Double = 0
    @State private var glowOpacity: Double = 0

    private let sparkColors: [Color] = [
        .appPrimary, .appAccent, .orange, .yellow, .pink, .green, .cyan
    ]

    var body: some View {
        ZStack {
            // Sparks
            ForEach(sparks) { spark in
                Circle()
                    .fill(spark.color)
                    .frame(width: spark.size, height: spark.size)
                    .offset(x: spark.x, y: spark.y)
                    .opacity(spark.opacity)
            }

            // Glow behind checkmark
            Circle()
                .fill(
                    RadialGradient(
                        colors: [Color.appPrimary.opacity(0.5), Color.clear],
                        center: .center,
                        startRadius: 10,
                        endRadius: 50
                    )
                )
                .frame(width: 100, height: 100)
                .opacity(glowOpacity)

            // Checkmark circle
            Circle()
                .fill(Color.appPrimary)
                .frame(width: 56, height: 56)
                .scaleEffect(checkmarkScale)
                .opacity(checkmarkOpacity)

            // Checkmark icon
            Image(systemName: "checkmark")
                .font(.system(size: 28, weight: .bold))
                .foregroundColor(.white)
                .scaleEffect(checkmarkScale)
                .opacity(checkmarkOpacity)
        }
        .onAppear {
            startAnimation()
        }
    }

    private func startAnimation() {
        // Generate sparks
        sparks = (0..<20).map { i in
            let angle = Double(i) * (360.0 / 20.0) * .pi / 180
            return FireworkSpark(
                id: i,
                color: sparkColors.randomElement()!,
                size: CGFloat.random(in: 4...10),
                x: 0,
                y: 0,
                targetX: cos(angle) * CGFloat.random(in: 60...100),
                targetY: sin(angle) * CGFloat.random(in: 60...100),
                opacity: 1.0
            )
        }

        // Explode sparks outward
        withAnimation(.easeOut(duration: 0.4)) {
            sparks = sparks.map { spark in
                var s = spark
                s.x = spark.targetX
                s.y = spark.targetY
                return s
            }
        }

        // Fade sparks and show glow
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
            withAnimation(.easeOut(duration: 0.4)) {
                sparks = sparks.map { spark in
                    var s = spark
                    s.opacity = 0
                    s.y += 20 // Slight gravity effect
                    return s
                }
                glowOpacity = 1.0
            }
        }

        // Show checkmark with bounce
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.35) {
            withAnimation(.spring(response: 0.4, dampingFraction: 0.5)) {
                checkmarkScale = 1.0
                checkmarkOpacity = 1.0
            }
        }

        // Fade out
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.8) {
            withAnimation(.easeOut(duration: 0.3)) {
                checkmarkScale = 0.8
                checkmarkOpacity = 0
                glowOpacity = 0
            }
        }
    }
}

private struct FireworkSpark: Identifiable {
    let id: Int
    let color: Color
    let size: CGFloat
    var x: CGFloat
    var y: CGFloat
    let targetX: CGFloat
    let targetY: CGFloat
    var opacity: Double
}

// MARK: - Starburst Checkmark Animation View

struct StarburstCheckmarkView: View {
    @State private var rayScale: CGFloat = 0
    @State private var rayOpacity: Double = 0
    @State private var rayRotation: Double = 0
    @State private var checkmarkScale: CGFloat = 0
    @State private var checkmarkOpacity: Double = 0
    @State private var pulseScale: CGFloat = 1.0

    private let rayCount = 12

    var body: some View {
        ZStack {
            // Radiating rays
            ForEach(0..<rayCount, id: \.self) { index in
                RoundedRectangle(cornerRadius: 2)
                    .fill(
                        LinearGradient(
                            colors: [Color.appAccent, Color.appAccent.opacity(0)],
                            startPoint: .bottom,
                            endPoint: .top
                        )
                    )
                    .frame(width: 4, height: 40)
                    .offset(y: -50)
                    .rotationEffect(.degrees(Double(index) * (360.0 / Double(rayCount)) + rayRotation))
                    .scaleEffect(rayScale)
                    .opacity(rayOpacity)
            }

            // Pulse ring
            Circle()
                .stroke(Color.appPrimary.opacity(0.3), lineWidth: 3)
                .frame(width: 70, height: 70)
                .scaleEffect(pulseScale)
                .opacity(2.0 - pulseScale)

            // Checkmark circle
            Circle()
                .fill(Color.appPrimary)
                .frame(width: 56, height: 56)
                .scaleEffect(checkmarkScale)
                .opacity(checkmarkOpacity)

            // Checkmark icon
            Image(systemName: "checkmark")
                .font(.system(size: 28, weight: .bold))
                .foregroundColor(.white)
                .scaleEffect(checkmarkScale)
                .opacity(checkmarkOpacity)
        }
        .onAppear {
            startAnimation()
        }
    }

    private func startAnimation() {
        // Burst rays outward with rotation
        withAnimation(.easeOut(duration: 0.4)) {
            rayScale = 1.0
            rayOpacity = 1.0
            rayRotation = 15
        }

        // Checkmark appears with spring
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) {
            withAnimation(.spring(response: 0.35, dampingFraction: 0.6)) {
                checkmarkScale = 1.0
                checkmarkOpacity = 1.0
            }
        }

        // Pulse ring expands
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
            withAnimation(.easeOut(duration: 0.6)) {
                pulseScale = 2.0
            }
        }

        // Rays fade
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
            withAnimation(.easeOut(duration: 0.4)) {
                rayOpacity = 0
                rayRotation = 30
            }
        }

        // Fade out
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.8) {
            withAnimation(.easeOut(duration: 0.3)) {
                checkmarkScale = 0.8
                checkmarkOpacity = 0
            }
        }
    }
}

// MARK: - Ripple Checkmark Animation View

struct RippleCheckmarkView: View {
    @State private var rings: [RippleRing] = []
    @State private var checkmarkScale: CGFloat = 0
    @State private var checkmarkOpacity: Double = 0

    var body: some View {
        ZStack {
            // Expanding rings
            ForEach(rings) { ring in
                Circle()
                    .stroke(Color.appPrimary.opacity(ring.opacity), lineWidth: ring.lineWidth)
                    .frame(width: ring.size, height: ring.size)
                    .scaleEffect(ring.scale)
            }

            // Checkmark circle
            Circle()
                .fill(Color.appPrimary)
                .frame(width: 56, height: 56)
                .scaleEffect(checkmarkScale)
                .opacity(checkmarkOpacity)

            // Checkmark icon
            Image(systemName: "checkmark")
                .font(.system(size: 28, weight: .bold))
                .foregroundColor(.white)
                .scaleEffect(checkmarkScale)
                .opacity(checkmarkOpacity)
        }
        .onAppear {
            startAnimation()
        }
    }

    private func startAnimation() {
        // Create initial rings
        rings = (0..<4).map { i in
            RippleRing(
                id: i,
                size: 60,
                scale: 0.5,
                opacity: 0.8,
                lineWidth: 3
            )
        }

        // Checkmark appears first with bounce
        withAnimation(.spring(response: 0.35, dampingFraction: 0.6)) {
            checkmarkScale = 1.0
            checkmarkOpacity = 1.0
        }

        // Animate rings outward with stagger
        for i in 0..<rings.count {
            DispatchQueue.main.asyncAfter(deadline: .now() + Double(i) * 0.15 + 0.1) {
                withAnimation(.easeOut(duration: 0.8)) {
                    if i < rings.count {
                        rings[i].scale = 2.5
                        rings[i].opacity = 0
                        rings[i].lineWidth = 1
                    }
                }
            }
        }

        // Fade out checkmark
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.8) {
            withAnimation(.easeOut(duration: 0.3)) {
                checkmarkScale = 0.8
                checkmarkOpacity = 0
            }
        }
    }
}

private struct RippleRing: Identifiable {
    let id: Int
    let size: CGFloat
    var scale: CGFloat
    var opacity: Double
    var lineWidth: CGFloat
}

// MARK: - Preview

#Preview("Implode Animation") {
    VStack(spacing: 40) {
        Text("Task Completion Animation")
            .font(.headline)

        ZStack {
            RoundedRectangle(cornerRadius: 12)
                .fill(Color.appBackgroundSecondary)
                .frame(width: 300, height: 100)

            Text("Sample Task Card")
                .foregroundColor(.appTextPrimary)

            TaskCompletionAnimation(isAnimating: .constant(true))
        }
    }
    .padding()
}
