//
//  YHVideoCell.swift
//  galaxy
//
//  Created by alexzzw on 2025/9/27.
//  Copyright © 2025 https://www.galaxy-immi.com. All rights reserved.
//

import Foundation
import UIKit
import AVFoundation
import JXPhotoBrowser
import SnapKit

class YHVideoCell: UIView, JXPhotoBrowserCell {
    
    weak var photoBrowser: JXPhotoBrowser?
    
    lazy var player = AVPlayer()
    lazy var playerLayer = AVPlayerLayer(player: player)
    
    // 播放状态图标
    lazy var playImageView: UIImageView = {
        let imageView = UIImageView()
        let playImage = UIImage(named: "circle_play_icon")?.withRenderingMode(.alwaysOriginal)
        imageView.image = playImage
        return imageView
    }()
    
    // 进度滑块
    lazy var progressSlider: UISlider = {
        let slider = UISlider()
        slider.minimumTrackTintColor = .white
        slider.maximumTrackTintColor = UIColor.white.withAlphaComponent(0.3)
        slider.thumbTintColor = .white
        slider.addTarget(self, action: #selector(sliderValueChanged), for: .valueChanged)
        slider.addTarget(self, action: #selector(sliderTouchDown), for: .touchDown)
        slider.addTarget(self, action: #selector(sliderTouchUp), for: .touchUpInside)
        slider.addTarget(self, action: #selector(sliderTouchUp), for: .touchUpOutside)
        return slider
    }()
    
    // 时间标签
    lazy var timeLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont.systemFont(ofSize: 12)
        label.textColor = .white
        label.text = "00:00 / 00:00"
        label.textAlignment = .right
        return label
    }()
    
    private var timeObserver: Any?
    private var isPlaying = false
    private var isSeeking = false
    
    static func generate(with browser: JXPhotoBrowser) -> Self {
        let instance = Self.init(frame: .zero)
        instance.photoBrowser = browser
        return instance
    }
    
    required override init(frame: CGRect) {
        super.init(frame: .zero)
        setupUI()
        setupGestures()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    deinit {
        removeTimeObserver()
        NotificationCenter.default.removeObserver(self)
    }
    
    private func setupUI() {
        backgroundColor = .black
        
        layer.addSublayer(playerLayer)
        addSubview(playImageView)
        addSubview(progressSlider)
        addSubview(timeLabel)
        
        setupConstraints()
        setupNotifications()
    }
    
    private func setupConstraints() {
        playImageView.snp.makeConstraints { make in
            make.center.equalToSuperview()
            make.width.height.equalTo(48)
        }
        
        progressSlider.snp.makeConstraints { make in
            make.left.right.equalToSuperview().inset(16)
            make.bottom.equalToSuperview().offset(-60)
            make.height.equalTo(30)
        }
        
        timeLabel.snp.makeConstraints { make in
            make.right.equalToSuperview().offset(-16)
            make.top.equalTo(progressSlider.snp.bottom).offset(8)
        }
    }
    
    private func setupGestures() {
        let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap))
        addGestureRecognizer(tap)
        
        let doubleTap = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap))
        doubleTap.numberOfTapsRequired = 2
        addGestureRecognizer(doubleTap)
        
        tap.require(toFail: doubleTap)
    }
    
    private func setupNotifications() {
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(playerDidFinishPlaying),
            name: .AVPlayerItemDidPlayToEndTime,
            object: nil
        )
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        playerLayer.frame = bounds
    }
    
    // MARK: - Actions
    @objc private func handleTap() {
        // 点击整个页面播放或暂停
        if isPlaying {
            pauseVideo()
        } else {
            playVideo()
        }
        
        // 显示/隐藏控制器
        toggleControlsVisibility()
    }
    
    @objc private func handleDoubleTap() {
        photoBrowser?.dismiss()
    }
    
    @objc private func sliderValueChanged(_ sender: UISlider) {
        guard let item = player.currentItem else { return }
        let duration = CMTimeGetSeconds(item.duration)
        if duration.isFinite && duration > 0 {
            let targetTime = Double(sender.value) * duration
            let currentTimeString = formatTime(targetTime)
            let durationString = formatTime(duration)
            timeLabel.text = "\(currentTimeString) / \(durationString)"
        }
    }
    
    @objc private func sliderTouchDown() {
        isSeeking = true
    }
    
    @objc private func sliderTouchUp() {
        guard let item = player.currentItem else { return }
        let duration = CMTimeGetSeconds(item.duration)
        if duration.isFinite && duration > 0 {
            let targetTime = Double(progressSlider.value) * duration
            let seekTime = CMTime(seconds: targetTime, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
            player.seek(to: seekTime) { [weak self] _ in
                self?.isSeeking = false
            }
        } else {
            isSeeking = false
        }
    }
    
    @objc private func playerDidFinishPlaying() {
        isPlaying = false
        playImageView.isHidden = false
        player.seek(to: CMTime.zero)
        progressSlider.value = 0
        updatePlayButtonImage()
    }
    
    // MARK: - Video Control
    func loadVideo(from url: URL) {
        let playerItem = AVPlayerItem(url: url)
        player.replaceCurrentItem(with: playerItem)
        addTimeObserver()
        updatePlayButtonImage()
    }
    
    func loadVideo(from urlString: String) {
        guard let url = URL(string: urlString) else { return }
        loadVideo(from: url)
    }
    
    func playVideo() {
        player.play()
        isPlaying = true
        playImageView.isHidden = true
        updatePlayButtonImage()
    }
    
    private func pauseVideo() {
        player.pause()
        isPlaying = false
        playImageView.isHidden = false
        updatePlayButtonImage()
    }
    
    func stopVideo() {
        player.pause()
        player.seek(to: CMTime.zero)
        isPlaying = false
        playImageView.isHidden = false
        progressSlider.value = 0
        updatePlayButtonImage()
    }
    
    private func updatePlayButtonImage() {
        let imageName = isPlaying ? "circle_pause_icon" : "circle_play_icon"
        let image = UIImage(named: imageName)?.withRenderingMode(.alwaysOriginal)
        playImageView.image = image
    }
    
    private func toggleControlsVisibility() {
        let isHidden = playImageView.alpha == 0
        UIView.animate(withDuration: 0.3) {
            self.playImageView.alpha = isHidden ? 1.0 : 0.0
            self.progressSlider.alpha = isHidden ? 1.0 : 0.0
            self.timeLabel.alpha = isHidden ? 1.0 : 0.0
        } completion: { _ in
            self.playImageView.isHidden = !isHidden && self.isPlaying
            self.progressSlider.isHidden = !isHidden
            self.timeLabel.isHidden = !isHidden
        }
    }
    
    // MARK: - Time Observer
    private func addTimeObserver() {
        let timeInterval = CMTime(seconds: 0.1, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
        timeObserver = player.addPeriodicTimeObserver(forInterval: timeInterval, queue: .main) { [weak self] _ in
            self?.updateProgress()
        }
    }
    
    private func removeTimeObserver() {
        if let timeObserver = timeObserver {
            player.removeTimeObserver(timeObserver)
            self.timeObserver = nil
        }
    }
    
    private func updateProgress() {
        guard let item = player.currentItem, !isSeeking else { return }
        
        let currentTime = CMTimeGetSeconds(player.currentTime())
        let duration = CMTimeGetSeconds(item.duration)
        
        if duration.isFinite && duration > 0 {
            progressSlider.value = Float(currentTime / duration)
            
            let currentTimeString = formatTime(currentTime)
            let durationString = formatTime(duration)
            timeLabel.text = "\(currentTimeString) / \(durationString)"
        }
    }
    
    private func formatTime(_ time: Double) -> String {
        if time.isInfinite || time.isNaN {
            return "00:00"
        }
        
        let minutes = Int(time) / 60
        let seconds = Int(time) % 60
        return String(format: "%02d:%02d", minutes, seconds)
    }
}
