import SwiftUI
import Lottie

/// Telegram-parity tab bar icon using Lottie animations.
///
/// Behaviour matches `TabBarComponent.ItemComponent` in Telegram-iOS:
/// - Displays the **last frame** at rest (`startingPosition: .end`)
/// - Plays **once** from start to end when the tab becomes selected
/// - Tinted with a single color via `ColorValueProvider` (Telegram: `setOverlayColor`)
struct TabBarLottieIcon: UIViewRepresentable {
    let animationName: String
    let color: Color
    /// Incremented each time the tab becomes selected — triggers a play.
    let playTrigger: Int

    func makeCoordinator() -> Coordinator { Coordinator() }

    final class Coordinator {
        var lastTrigger: Int = 0
        var currentName: String = ""
        var lastColorHex: UInt64 = .max // cache to skip redundant setValueProvider
    }

    func makeUIView(context: Context) -> LottieAnimationView {
        let view = LottieAnimationView()
        view.contentMode = .scaleAspectFit
        view.isUserInteractionEnabled = false
        view.backgroundBehavior = .pauseAndRestore
        // CRITICAL: allow SwiftUI .frame() to constrain the view.
        // Without this, LottieAnimationView reports intrinsicContentSize 512×512
        // (from the JSON canvas) and SwiftUI cannot shrink it.
        view.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
        view.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
        view.setContentHuggingPriority(.required, for: .horizontal)
        view.setContentHuggingPriority(.required, for: .vertical)
        view.clipsToBounds = true
        loadAnimation(into: view, context: context)
        return view
    }

    func updateUIView(_ uiView: LottieAnimationView, context: Context) {
        if context.coordinator.currentName != animationName {
            loadAnimation(into: uiView, context: context)
        }

        applyColorIfNeeded(uiView, coordinator: context.coordinator)

        if context.coordinator.lastTrigger != playTrigger {
            context.coordinator.lastTrigger = playTrigger
            uiView.play(fromProgress: 0, toProgress: 1, loopMode: .playOnce)
        }
    }

    private func loadAnimation(into view: LottieAnimationView, context: Context) {
        if let cached = LottieAnimationCache.shared.animation(named: animationName) {
            view.animation = cached
        } else {
            view.animation = LottieAnimation.named(animationName)
        }
        view.loopMode = .playOnce
        view.currentProgress = 1.0
        context.coordinator.currentName = animationName
        context.coordinator.lastTrigger = playTrigger
        context.coordinator.lastColorHex = .max // force color apply
        applyColorIfNeeded(view, coordinator: context.coordinator)
    }

    private func applyColorIfNeeded(_ view: LottieAnimationView, coordinator: Coordinator) {
        let hex = colorToHex(color)
        guard hex != coordinator.lastColorHex else { return }
        coordinator.lastColorHex = hex

        var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0
        UIColor(color).getRed(&r, green: &g, blue: &b, alpha: &a)
        let lottieColor = LottieColor(r: Double(r), g: Double(g), b: Double(b), a: Double(a))
        view.setValueProvider(
            ColorValueProvider(lottieColor),
            keypath: AnimationKeypath(keypath: "**.Color")
        )
    }

    private func colorToHex(_ c: Color) -> UInt64 {
        var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0
        UIColor(c).getRed(&r, green: &g, blue: &b, alpha: &a)
        let ri = UInt64(r * 255) << 24
        let gi = UInt64(g * 255) << 16
        let bi = UInt64(b * 255) << 8
        let ai = UInt64(a * 255)
        return ri | gi | bi | ai
    }
}
