//
//  HapticFeedbackManager.swift
//  Reflect
//
//  Haptic feedback patterns that match celebration animations.
//

import UIKit
import CoreHaptics

@MainActor
final class HapticFeedbackManager {
    static let shared = HapticFeedbackManager()

    private var engine: CHHapticEngine?

    private init() {
        prepareEngine()
    }

    private func prepareEngine() {
        guard CHHapticEngine.capabilitiesForHardware().supportsHaptics else { return }
        do {
            engine = try CHHapticEngine()
            engine?.resetHandler = { [weak self] in
                try? self?.engine?.start()
            }
            try engine?.start()
        } catch {
            engine = nil
        }
    }

    /// Play a haptic pattern that matches the given celebration animation type.
    func play(for animationType: CelebrationAnimationType) {
        guard CHHapticEngine.capabilitiesForHardware().supportsHaptics,
              let engine else {
            // Fall back to basic haptic on devices without CoreHaptics
            let generator = UIImpactFeedbackGenerator(style: .medium)
            generator.impactOccurred()
            return
        }

        do {
            let pattern = try hapticPattern(for: animationType)
            let player = try engine.makePlayer(with: pattern)
            try engine.start()
            try player.start(atTime: CHHapticTimeImmediate)
        } catch {
            // Fallback to simple impact
            let generator = UIImpactFeedbackGenerator(style: .medium)
            generator.impactOccurred()
        }
    }

    // MARK: - Pattern Definitions

    private func hapticPattern(for animationType: CelebrationAnimationType) throws -> CHHapticPattern {
        switch animationType {
        case .confettiCannon:
            return try confettiPattern()
        case .vortexCheckmark:
            return try vortexPattern()
        case .explosionReveal:
            return try explosionPattern()
        case .flipReveal:
            return try flipPattern()
        case .shatterReform:
            return try shatterPattern()
        case .pulseWave:
            return try pulseWavePattern()
        case .fireworks:
            return try fireworksPattern()
        case .morphBlob:
            return try morphPattern()
        case .zoomTunnel:
            return try tunnelPattern()
        case .gravityDrop:
            return try gravityPattern()
        }
    }

    // Confetti: poppy burst upward → checkmark spring → light scattered taps falling like confetti
    // Visual: 0.0 launch + glow | 0.3 checkmark spring | 0.5 confetti falling | 1.3 fade
    private func confettiPattern() throws -> CHHapticPattern {
        var events: [CHHapticEvent] = []

        // Cannon pop — sharp, bright, like a party popper
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.9),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 1.0)
            ],
            relativeTime: 0.0
        ))

        // Checkmark spring-in at 0.3s
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.7),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.5)
            ],
            relativeTime: 0.3
        ))

        // Confetti pieces falling — light, playful, irregular taps with varying sharpness
        let confettiTimes: [Double] = [0.55, 0.65, 0.72, 0.82, 0.93, 1.05, 1.15, 1.25, 1.35, 1.45]
        let sharpnesses: [Float] = [0.9, 0.5, 0.8, 0.3, 0.7, 0.4, 0.6, 0.3, 0.5, 0.2]
        for (i, time) in confettiTimes.enumerated() {
            let intensity = Float(0.4 - Double(i) * 0.03)
            events.append(CHHapticEvent(
                eventType: .hapticTransient,
                parameters: [
                    CHHapticEventParameter(parameterID: .hapticIntensity, value: max(intensity, 0.1)),
                    CHHapticEventParameter(parameterID: .hapticSharpness, value: sharpnesses[i])
                ],
                relativeTime: time
            ))
        }

        return try CHHapticPattern(events: events, parameters: [])
    }

    // Vortex: spirals spin 0–0.5s → ring snaps at 0.3s → checkmark pops 0.5s → settles 0.7s
    // Character: whirring buildup with accelerating ticks, then a tight satisfying snap
    private func vortexPattern() throws -> CHHapticPattern {
        var events: [CHHapticEvent] = []

        // Spinning wind-up — accelerating ticks like a roulette wheel slowing in reverse
        let tickTimes: [Double] = [0.0, 0.07, 0.13, 0.18, 0.22, 0.25, 0.27, 0.29, 0.30]
        for (i, time) in tickTimes.enumerated() {
            let progress = Float(i) / Float(tickTimes.count)
            events.append(CHHapticEvent(
                eventType: .hapticTransient,
                parameters: [
                    CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.15 + progress * 0.4),
                    CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.2 + progress * 0.3)
                ],
                relativeTime: time
            ))
        }

        // Ring appears — soft thrum
        events.append(CHHapticEvent(
            eventType: .hapticContinuous,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.5),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.2)
            ],
            relativeTime: 0.3,
            duration: 0.2
        ))

        // Checkmark pops — the payoff snap
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 1.0),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.6)
            ],
            relativeTime: 0.5
        ))

        // Checkmark settles — soft bounce
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.3),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.3)
            ],
            relativeTime: 0.7
        ))

        return try CHHapticPattern(events: events, parameters: [])
    }

    // Explosion: particles fly out 0–0.6s → glow 0.2–0.6s → checkmark drops in 0.3s → fades 1.4s
    // Character: massive singular BOOM then debris scattering away — the biggest hit of any animation
    private func explosionPattern() throws -> CHHapticPattern {
        var events: [CHHapticEvent] = []

        // THE explosion — maximum everything, low sharpness for deep boom
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 1.0),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.1)
            ],
            relativeTime: 0.0
        ))

        // Shockwave rumble — deep, low, fading
        events.append(CHHapticEvent(
            eventType: .hapticContinuous,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.7),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.1)
            ],
            relativeTime: 0.02,
            duration: 0.35
        ))

        // Debris particles hitting — scattered sharp ticks as pieces fly
        let debrisTimes: [Double] = [0.12, 0.18, 0.25, 0.32, 0.40]
        for (i, time) in debrisTimes.enumerated() {
            events.append(CHHapticEvent(
                eventType: .hapticTransient,
                parameters: [
                    CHHapticEventParameter(parameterID: .hapticIntensity, value: Float(0.5 - Double(i) * 0.08)),
                    CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.9)
                ],
                relativeTime: time
            ))
        }

        // Checkmark drops in — solid medium thud (not as big as the explosion)
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.6),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.4)
            ],
            relativeTime: 0.55
        ))

        let curve = CHHapticParameterCurve(
            parameterID: .hapticIntensityControl,
            controlPoints: [
                CHHapticParameterCurve.ControlPoint(relativeTime: 0.0, value: 1.0),
                CHHapticParameterCurve.ControlPoint(relativeTime: 0.15, value: 0.6),
                CHHapticParameterCurve.ControlPoint(relativeTime: 0.4, value: 0.1)
            ],
            relativeTime: 0.0
        )

        return try CHHapticPattern(events: events, parameterCurves: [curve])
    }

    // Flip: card flips at 0.2s → checkmark scales 0.4s → shimmer sweeps 0.5–1.3s
    // Character: clean, elegant — a crisp two-beat flip then a silky shimmer glide
    private func flipPattern() throws -> CHHapticPattern {
        var events: [CHHapticEvent] = []

        // Card lifts off surface — gentle click
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.3),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.7)
            ],
            relativeTime: 0.2
        ))

        // Card slaps down — the satisfying flip landing
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.8),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.4)
            ],
            relativeTime: 0.4
        ))

        // Checkmark bounce
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.4),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.3)
            ],
            relativeTime: 0.6
        ))

        // Shimmer sweeping across — very light, high-sharpness continuous (like a sparkle)
        events.append(CHHapticEvent(
            eventType: .hapticContinuous,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.15),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 1.0)
            ],
            relativeTime: 0.5,
            duration: 0.8
        ))

        let shimmerCurve = CHHapticParameterCurve(
            parameterID: .hapticIntensityControl,
            controlPoints: [
                CHHapticParameterCurve.ControlPoint(relativeTime: 0.5, value: 0.0),
                CHHapticParameterCurve.ControlPoint(relativeTime: 0.7, value: 1.0),
                CHHapticParameterCurve.ControlPoint(relativeTime: 1.3, value: 0.0)
            ],
            relativeTime: 0.0
        )

        return try CHHapticPattern(events: events, parameterCurves: [shimmerCurve])
    }

    // Shatter: explode out 0–0.5s → pause → converge 0.6–1.1s → checkmark 1.1s → fade 1.8s
    // Character: glass breaking — sharp crack, scattered sharp hits, silence, then magnetic pull + click
    private func shatterPattern() throws -> CHHapticPattern {
        var events: [CHHapticEvent] = []

        // Glass crack — extremely sharp and crisp
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 1.0),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 1.0)
            ],
            relativeTime: 0.0
        ))

        // Shards flying — sharp, glassy ticks scattering outward
        let shardTimes: [Double] = [0.04, 0.08, 0.13, 0.19, 0.26, 0.35, 0.45]
        for (i, time) in shardTimes.enumerated() {
            events.append(CHHapticEvent(
                eventType: .hapticTransient,
                parameters: [
                    CHHapticEventParameter(parameterID: .hapticIntensity, value: Float(0.6 - Double(i) * 0.07)),
                    CHHapticEventParameter(parameterID: .hapticSharpness, value: 1.0)
                ],
                relativeTime: time
            ))
        }

        // ---- silence / gap while pieces float (0.5–0.6s) ----

        // Reform — pieces pulling back, low magnetic hum building
        events.append(CHHapticEvent(
            eventType: .hapticContinuous,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.2),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.1)
            ],
            relativeTime: 0.6,
            duration: 0.5
        ))

        let reformCurve = CHHapticParameterCurve(
            parameterID: .hapticIntensityControl,
            controlPoints: [
                CHHapticParameterCurve.ControlPoint(relativeTime: 0.6, value: 0.1),
                CHHapticParameterCurve.ControlPoint(relativeTime: 1.0, value: 0.6)
            ],
            relativeTime: 0.0
        )

        // Final snap together — satisfying click as pieces lock in
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.9),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.6)
            ],
            relativeTime: 1.1
        ))

        return try CHHapticPattern(events: events, parameterCurves: [reformCurve])
    }

    // Pulse: waves at 0.0, 0.1, 0.2 → stamp checkmark at 0.2s with rotation → fade 1.2s
    // Character: rhythmic heartbeat pulses then a heavy rubber-stamp DOWN
    private func pulseWavePattern() throws -> CHHapticPattern {
        var events: [CHHapticEvent] = []

        // Three wave pulses — each softer and more diffuse, like ripples spreading
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.6),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.2)
            ],
            relativeTime: 0.0
        ))
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.4),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.15)
            ],
            relativeTime: 0.1
        ))
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.25),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.1)
            ],
            relativeTime: 0.2
        ))

        // STAMP DOWN — heavy, authoritative, like a rubber stamp slamming
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 1.0),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.3)
            ],
            relativeTime: 0.25
        ))

        // Stamp reverb — brief low rumble from the impact
        events.append(CHHapticEvent(
            eventType: .hapticContinuous,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.3),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.05)
            ],
            relativeTime: 0.27,
            duration: 0.2
        ))

        return try CHHapticPattern(events: events, parameters: [])
    }

    // Fireworks: 4 bursts staggered at 0.0/0.15/0.30/0.45 → checkmark at 0.6s → fade 2.0s
    // Character: distinct pops at different heights/intensities, each with a quick sparkle trail
    private func fireworksPattern() throws -> CHHapticPattern {
        var events: [CHHapticEvent] = []

        // Burst 1 — big opening burst
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.9),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.7)
            ],
            relativeTime: 0.0
        ))
        // Sparkle trail
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.3),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 1.0)
            ],
            relativeTime: 0.08
        ))

        // Burst 2 — smaller, higher pitch
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.6),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.9)
            ],
            relativeTime: 0.15
        ))
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.2),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 1.0)
            ],
            relativeTime: 0.22
        ))

        // Burst 3 — deep thump
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.8),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.3)
            ],
            relativeTime: 0.30
        ))
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.25),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.8)
            ],
            relativeTime: 0.37
        ))

        // Burst 4 — grand finale, biggest
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 1.0),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.5)
            ],
            relativeTime: 0.45
        ))
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.4),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.9)
            ],
            relativeTime: 0.52
        ))

        // Checkmark — gentle after the show
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.5),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.4)
            ],
            relativeTime: 0.65
        ))

        return try CHHapticPattern(events: events, parameters: [])
    }

    // Morph: blobs expand 0–0.4s → morph/shift 0.4–0.9s → converge 0.9–1.3s → checkmark 1.2s
    // Character: liquid, organic — continuous flowing hum that breathes and undulates
    private func morphPattern() throws -> CHHapticPattern {
        var events: [CHHapticEvent] = []

        // Blob expand — soft, round, growing
        events.append(CHHapticEvent(
            eventType: .hapticContinuous,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.3),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.05)
            ],
            relativeTime: 0.0,
            duration: 0.4
        ))

        // Morph shift — blobs moving, undulating, slightly sharper
        events.append(CHHapticEvent(
            eventType: .hapticContinuous,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.4),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.1)
            ],
            relativeTime: 0.4,
            duration: 0.5
        ))

        // Intensity curve for the morph — breathing/pulsing feel
        let morphCurve = CHHapticParameterCurve(
            parameterID: .hapticIntensityControl,
            controlPoints: [
                CHHapticParameterCurve.ControlPoint(relativeTime: 0.0, value: 0.3),
                CHHapticParameterCurve.ControlPoint(relativeTime: 0.2, value: 0.5),
                CHHapticParameterCurve.ControlPoint(relativeTime: 0.4, value: 0.3),
                CHHapticParameterCurve.ControlPoint(relativeTime: 0.6, value: 0.6),
                CHHapticParameterCurve.ControlPoint(relativeTime: 0.8, value: 0.4),
                CHHapticParameterCurve.ControlPoint(relativeTime: 0.9, value: 0.8)
            ],
            relativeTime: 0.0
        )

        // Converge — blobs snap together, soft thud
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.5),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.15)
            ],
            relativeTime: 0.9
        ))

        // Checkmark — soft glow reveal, not sharp
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.6),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.2)
            ],
            relativeTime: 1.2
        ))

        return try CHHapticPattern(events: events, parameterCurves: [morphCurve])
    }

    // Tunnel: 6 rings zoom in (each 0.1s delay) → starburst rotates → checkmark 0.5s → fade 1.5s
    // Character: accelerating whoosh — rings pass you faster and faster, then BAM you arrive
    private func tunnelPattern() throws -> CHHapticPattern {
        var events: [CHHapticEvent] = []

        // Rings passing — accelerating rhythm (gaps get shorter), each ring is a whoosh
        // Visual: rings at 0.0, 0.1, 0.2, 0.3, 0.4, 0.5 with scale animation
        let ringTimes: [Double] = [0.0, 0.08, 0.14, 0.19, 0.23, 0.26]
        for (i, time) in ringTimes.enumerated() {
            let progress = Float(i) / Float(ringTimes.count)
            // Each ring hit gets more intense and slightly sharper
            events.append(CHHapticEvent(
                eventType: .hapticTransient,
                parameters: [
                    CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.15 + progress * 0.5),
                    CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.4 + progress * 0.3)
                ],
                relativeTime: time
            ))
        }

        // Warp speed — continuous buzzy rush as you fly through
        events.append(CHHapticEvent(
            eventType: .hapticContinuous,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.6),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.7)
            ],
            relativeTime: 0.28,
            duration: 0.2
        ))

        let warpCurve = CHHapticParameterCurve(
            parameterID: .hapticIntensityControl,
            controlPoints: [
                CHHapticParameterCurve.ControlPoint(relativeTime: 0.28, value: 0.4),
                CHHapticParameterCurve.ControlPoint(relativeTime: 0.38, value: 1.0),
                CHHapticParameterCurve.ControlPoint(relativeTime: 0.48, value: 0.8)
            ],
            relativeTime: 0.0
        )

        // Arrival — big thud as you land at the destination
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 1.0),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.5)
            ],
            relativeTime: 0.5
        ))

        // Starburst shimmer — light rotating sparkle
        events.append(CHHapticEvent(
            eventType: .hapticContinuous,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.15),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.9)
            ],
            relativeTime: 0.55,
            duration: 0.3
        ))

        return try CHHapticPattern(events: events, parameterCurves: [warpCurve])
    }

    // Gravity: falls 0–0.4s → impact 0.4s → bounce up 0.4–0.6 → down 0.6 → up 0.6–0.75 → down 0.75 → settle 0.85
    // Character: weighty — falling acceleration, HEAVY impact, realistic diminishing bounces
    private func gravityPattern() throws -> CHHapticPattern {
        var events: [CHHapticEvent] = []

        // Falling — accelerating continuous that builds
        events.append(CHHapticEvent(
            eventType: .hapticContinuous,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.15),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.2)
            ],
            relativeTime: 0.0,
            duration: 0.38
        ))

        let fallCurve = CHHapticParameterCurve(
            parameterID: .hapticIntensityControl,
            controlPoints: [
                CHHapticParameterCurve.ControlPoint(relativeTime: 0.0, value: 0.05),
                CHHapticParameterCurve.ControlPoint(relativeTime: 0.2, value: 0.2),
                CHHapticParameterCurve.ControlPoint(relativeTime: 0.38, value: 0.9)
            ],
            relativeTime: 0.0
        )

        // FIRST IMPACT — heaviest, low and boomy (this is a heavy object hitting ground)
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 1.0),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.15)
            ],
            relativeTime: 0.4
        ))
        // Dust/ring burst from impact
        events.append(CHHapticEvent(
            eventType: .hapticContinuous,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.4),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.3)
            ],
            relativeTime: 0.41,
            duration: 0.12
        ))

        // Bounce 1 — lands again, lighter
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.55),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.2)
            ],
            relativeTime: 0.6
        ))

        // Bounce 2 — smaller
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.3),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.25)
            ],
            relativeTime: 0.75
        ))

        // Final settle — tiny tap
        events.append(CHHapticEvent(
            eventType: .hapticTransient,
            parameters: [
                CHHapticEventParameter(parameterID: .hapticIntensity, value: 0.12),
                CHHapticEventParameter(parameterID: .hapticSharpness, value: 0.2)
            ],
            relativeTime: 0.85
        ))

        return try CHHapticPattern(events: events, parameterCurves: [fallCurve])
    }
}
