//
//  VoiceWaveView.swift
//  Dialog_Demo
//
//  语音动效视图，基于 Core Animation 实现呼吸发光球体
//

import UIKit
import SnapKit

// MARK: - VoiceState 枚举

enum VoiceState {
    case idle
    case listening
    case thinking
    case responding
}

// MARK: - VoiceWaveView

/// 语音动效视图，基于 Core Animation 实现呼吸发光球体
class VoiceWaveView: UIView {

    // MARK: - Constants

    private enum Constants {
        static let diameter: CGFloat = 120
        static let glowPadding: CGFloat = 40
        static let transitionDuration: TimeInterval = 0.4
    }

    // MARK: - State Configuration

    private struct StateConfig {
        let primaryColor: UIColor
        let glowColor: UIColor
        let scaleRange: (min: CGFloat, max: CGFloat)
        let breathDuration: TimeInterval
        let glowOpacity: Float
    }

    private func config(for state: VoiceState) -> StateConfig {
        switch state {
        case .idle:
            // 浅灰蓝色 #B0C4DE，缓慢微弱呼吸
            return StateConfig(
                primaryColor: UIColor(red: 0xB0/255.0, green: 0xC4/255.0, blue: 0xDE/255.0, alpha: 1.0),
                glowColor: UIColor(red: 0xB0/255.0, green: 0xC4/255.0, blue: 0xDE/255.0, alpha: 0.25),
                scaleRange: (min: 0.97, max: 1.0),
                breathDuration: 3.5,
                glowOpacity: 0.15
            )
        case .listening:
            // 柔和蓝色 #7AB8F5，正常脉冲
            return StateConfig(
                primaryColor: UIColor(red: 0x7A/255.0, green: 0xB8/255.0, blue: 0xF5/255.0, alpha: 1.0),
                glowColor: UIColor(red: 0x7A/255.0, green: 0xB8/255.0, blue: 0xF5/255.0, alpha: 0.35),
                scaleRange: (min: 0.92, max: 1.05),
                breathDuration: 1.8,
                glowOpacity: 0.35
            )
        case .thinking:
            // 淡紫蓝色 #A78BFA，缓慢旋转感
            return StateConfig(
                primaryColor: UIColor(red: 0xA7/255.0, green: 0x8B/255.0, blue: 0xFA/255.0, alpha: 1.0),
                glowColor: UIColor(red: 0xA7/255.0, green: 0x8B/255.0, blue: 0xFA/255.0, alpha: 0.35),
                scaleRange: (min: 0.94, max: 1.04),
                breathDuration: 2.4,
                glowOpacity: 0.4
            )
        case .responding:
            // 青绿色 #34D399，较快脉冲（与 listening 蓝色区分）
            return StateConfig(
                primaryColor: UIColor(red: 0x34/255.0, green: 0xD3/255.0, blue: 0x99/255.0, alpha: 1.0),
                glowColor: UIColor(red: 0x34/255.0, green: 0xD3/255.0, blue: 0x99/255.0, alpha: 0.4),
                scaleRange: (min: 0.88, max: 1.08),
                breathDuration: 1.4,
                glowOpacity: 0.45
            )
        }
    }

    // MARK: - Properties

    private(set) var currentState: VoiceState = .idle

    /// 当前音量级别 (0.0~1.0)
    private var amplitude: Float = 0.0
    private var isAnimating = false

    // MARK: - UI Layers

    /// 外层光晕（径向渐变）
    private lazy var glowLayer: CAGradientLayer = {
        let layer = CAGradientLayer()
        layer.type = .radial
        layer.startPoint = CGPoint(x: 0.5, y: 0.5)
        layer.endPoint = CGPoint(x: 1.0, y: 1.0)
        let cfg = config(for: .idle)
        layer.colors = [
            cfg.glowColor.cgColor,
            cfg.glowColor.withAlphaComponent(0.05).cgColor,
            UIColor.clear.cgColor
        ]
        layer.locations = [0.0, 0.55, 1.0]
        layer.opacity = cfg.glowOpacity
        return layer
    }()

    /// 球体主体（径向渐变实现立体感）
    private lazy var sphereLayer: CAGradientLayer = {
        let layer = CAGradientLayer()
        layer.type = .radial
        // 高光偏左上
        layer.startPoint = CGPoint(x: 0.35, y: 0.35)
        layer.endPoint = CGPoint(x: 1.0, y: 1.0)
        let cfg = config(for: .idle)
        layer.colors = [
            cfg.primaryColor.withAlphaComponent(0.9).cgColor,
            cfg.primaryColor.withAlphaComponent(0.6).cgColor,
            cfg.primaryColor.withAlphaComponent(0.25).cgColor
        ]
        layer.locations = [0.0, 0.5, 1.0]
        layer.cornerRadius = Constants.diameter / 2
        layer.masksToBounds = true
        return layer
    }()

    /// 球体内部高光点
    private lazy var highlightLayer: CAGradientLayer = {
        let layer = CAGradientLayer()
        layer.type = .radial
        layer.startPoint = CGPoint(x: 0.5, y: 0.5)
        layer.endPoint = CGPoint(x: 1.0, y: 1.0)
        layer.colors = [
            UIColor.white.withAlphaComponent(0.35).cgColor,
            UIColor.white.withAlphaComponent(0.0).cgColor
        ]
        layer.locations = [0.0, 1.0]
        return layer
    }()

    /// 球体容器视图（用于整体缩放动画）
    private lazy var sphereContainer: UIView = {
        let v = UIView()
        v.backgroundColor = .clear
        return v
    }()

    // MARK: - Initialization

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupView()
    }

    deinit {
        stopAnimating()
    }

    // MARK: - Setup

    private func setupView() {
        backgroundColor = .clear

        // 外发光层
        layer.addSublayer(glowLayer)

        // 球体容器
        addSubview(sphereContainer)
        sphereContainer.snp.makeConstraints { make in
            make.center.equalToSuperview()
            make.width.height.equalTo(Constants.diameter)
        }

        // 球体渐变
        sphereContainer.layer.addSublayer(sphereLayer)

        // 高光
        sphereContainer.layer.addSublayer(highlightLayer)

        // 自身大小约束
        snp.makeConstraints { make in
            make.width.height.equalTo(Constants.diameter + Constants.glowPadding * 2)
        }
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        let totalSize = Constants.diameter + Constants.glowPadding * 2
        glowLayer.frame = CGRect(
            x: (bounds.width - totalSize) / 2,
            y: (bounds.height - totalSize) / 2,
            width: totalSize,
            height: totalSize
        )
        glowLayer.cornerRadius = totalSize / 2

        let sphereBounds = CGRect(x: 0, y: 0, width: Constants.diameter, height: Constants.diameter)
        sphereLayer.frame = sphereBounds

        // 高光在左上角
        let highlightSize = Constants.diameter * 0.45
        highlightLayer.frame = CGRect(
            x: Constants.diameter * 0.15,
            y: Constants.diameter * 0.12,
            width: highlightSize,
            height: highlightSize
        )
        highlightLayer.cornerRadius = highlightSize / 2
    }

    override func removeFromSuperview() {
        stopAnimating()
        super.removeFromSuperview()
    }

    // MARK: - Public Interface

    /// 切换状态（带平滑过渡动画）
    func setState(_ state: VoiceState) {
        guard state != currentState else { return }
        currentState = state

        let cfg = config(for: state)

        // 平滑过渡颜色
        CATransaction.begin()
        CATransaction.setAnimationDuration(Constants.transitionDuration)
        CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: .easeInEaseOut))

        sphereLayer.colors = [
            cfg.primaryColor.withAlphaComponent(0.9).cgColor,
            cfg.primaryColor.withAlphaComponent(0.6).cgColor,
            cfg.primaryColor.withAlphaComponent(0.25).cgColor
        ]

        glowLayer.colors = [
            cfg.glowColor.cgColor,
            cfg.glowColor.withAlphaComponent(0.05).cgColor,
            UIColor.clear.cgColor
        ]
        glowLayer.opacity = cfg.glowOpacity

        CATransaction.commit()

        // 重新启动呼吸动画以匹配新状态
        if isAnimating {
            applyBreathAnimation(config: cfg)
            if state == .thinking {
                applyRotationAnimation()
            } else {
                sphereContainer.layer.removeAnimation(forKey: "rotationAnimation")
            }
        }
    }

    /// 传入音量值 (0.0~1.0)，影响球体脉冲幅度
    func updateAmplitude(_ level: Float) {
        amplitude = min(max(level, 0.0), 1.0)

        // 根据音量动态调整当前缩放（叠加在呼吸动画上）
        let cfg = config(for: currentState)
        let extraScale = CGFloat(amplitude) * 0.08
        let currentScale = (cfg.scaleRange.min + cfg.scaleRange.max) / 2 + extraScale

        // 使用弹簧动画快速响应音量变化
        UIView.animate(withDuration: 0.1, delay: 0, options: .curveEaseOut) {
            self.sphereContainer.transform = CGAffineTransform(scaleX: currentScale, y: currentScale)
        }
    }

    /// 启动动画
    func startAnimating() {
        guard !isAnimating else { return }
        isAnimating = true

        let cfg = config(for: currentState)
        applyBreathAnimation(config: cfg)
        applyGlowPulseAnimation()

        if currentState == .thinking {
            applyRotationAnimation()
        }
    }

    /// 停止动画（释放资源）
    func stopAnimating() {
        isAnimating = false
        sphereContainer.layer.removeAllAnimations()
        glowLayer.removeAllAnimations()
    }

    // MARK: - Animation Implementations

    /// 呼吸缩放动画
    private func applyBreathAnimation(config cfg: StateConfig) {
        sphereContainer.layer.removeAnimation(forKey: "breathAnimation")

        let scaleX = CABasicAnimation(keyPath: "transform.scale.x")
        scaleX.fromValue = cfg.scaleRange.min
        scaleX.toValue = cfg.scaleRange.max

        let scaleY = CABasicAnimation(keyPath: "transform.scale.y")
        scaleY.fromValue = cfg.scaleRange.min
        scaleY.toValue = cfg.scaleRange.max

        let group = CAAnimationGroup()
        group.animations = [scaleX, scaleY]
        group.duration = cfg.breathDuration
        group.autoreverses = true
        group.repeatCount = .infinity
        group.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
        group.isRemovedOnCompletion = false
        group.fillMode = .forwards

        sphereContainer.layer.add(group, forKey: "breathAnimation")
    }

    /// 光晕脉冲动画
    private func applyGlowPulseAnimation() {
        glowLayer.removeAnimation(forKey: "glowPulse")

        let opacityAnim = CABasicAnimation(keyPath: "opacity")
        opacityAnim.fromValue = glowLayer.opacity
        opacityAnim.toValue = glowLayer.opacity * 0.5

        let scaleAnim = CABasicAnimation(keyPath: "transform.scale")
        scaleAnim.fromValue = 1.0
        scaleAnim.toValue = 1.08

        let group = CAAnimationGroup()
        group.animations = [opacityAnim, scaleAnim]
        group.duration = 2.5
        group.autoreverses = true
        group.repeatCount = .infinity
        group.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
        group.isRemovedOnCompletion = false
        group.fillMode = .forwards

        glowLayer.add(group, forKey: "glowPulse")
    }

    /// Thinking 状态旋转光晕动画
    private func applyRotationAnimation() {
        sphereContainer.layer.removeAnimation(forKey: "rotationAnimation")

        let rotation = CABasicAnimation(keyPath: "transform.rotation.z")
        rotation.fromValue = 0
        rotation.toValue = CGFloat.pi * 2
        rotation.duration = 6.0
        rotation.repeatCount = .infinity
        rotation.isRemovedOnCompletion = false
        rotation.fillMode = .forwards

        sphereContainer.layer.add(rotation, forKey: "rotationAnimation")
    }
}
