//
//  LNUploadVideioView.swift
//  Gami
//
//  Created by OneeChan on 2026/2/27.
//

import Foundation
import UIKit
import SnapKit
import AVFoundation


protocol LNVideoUploadViewDelegate: AnyObject {
    func onVideoUploadView(view: LNVideoUploadView, didUploadVideo url: String, imageUrl: String)
    func onVideoUploadViewUploadFailed(view: LNVideoUploadView)
    func onVideoUploadViewStartUpload(view: LNVideoUploadView)
    func onVideoUploadViewDidClickDelete(view: LNVideoUploadView)
}
extension LNVideoUploadViewDelegate {
    func onVideoUploadView(view: LNVideoUploadView, didUploadVideo url: String, imageUrl: String) {}
    func onVideoUploadViewUploadFailed(view: LNVideoUploadView) { }
    func onVideoUploadViewStartUpload(view: LNVideoUploadView) {}
    func onVideoUploadViewDidClickDelete(view: LNVideoUploadView) {}
}


class LNVideoUploadView: UIImageView {
    private var curTask: String?
    private(set) var sourceUrl: URL?
    private var cacheUrl: URL?
    private(set) var videoSize: CGSize?
    private(set) var videoUrl: String?
    private(set) var imageUrl: String?
    
    private let durationLabel = UILabel()
    private let playButton = UIButton()
    private let deleteButton = UIButton()
    
    weak var delegate: LNVideoUploadViewDelegate?
    
    override init(image: UIImage? = nil) {
        super.init(image: image)
        
        setupViews()
    }
    
    func preview(url: URL) -> CGSize {
        reset()
        
        guard FileManager.default.fileExists(atPath: url.path) else {
            return .zero
        }
        
        sourceUrl = url
        
        let asset = AVAsset(url: url)
        let videoDuration = CMTimeGetSeconds(asset.duration)
        durationLabel.text = videoDuration.timeCountDisplay
        
        DispatchQueue.global().async { [weak self] in
            guard let self else { return }
            guard sourceUrl == url else { return }
            
            // 创建缩略图生成器
            let imageGenerator = AVAssetImageGenerator(asset: asset)
            // 设置生成的图片比例（保持原视频比例）
            imageGenerator.appliesPreferredTrackTransform = true
            
            // 获取视频首帧作为预览图
            let time = CMTimeMakeWithSeconds(0, preferredTimescale: 600)
            do {
                // 生成指定时间点的图片
                let cgImage = try imageGenerator.copyCGImage(at: time, actualTime: nil)
                let thumbnailImage = UIImage(cgImage: cgImage)
                // 更新UI（必须在主线程）
                runOnMain {
                    self.image = thumbnailImage
                }
            } catch {
                print("生成视频缩略图失败：\(error.localizedDescription)")
                // 生成失败时显示占位图
                runOnMain {
                    self.image = UIImage(systemName: "film")
                }
            }
        }
        
        guard let videoTrack = asset.tracks(withMediaType: .video).first else {
            return .zero
        }
        // 3. 获取视频的自然尺寸（原始尺寸）
        let naturalSize = videoTrack.naturalSize
        
        // 4. 处理视频的旋转角度（避免尺寸方向错误）
        let transform = videoTrack.preferredTransform
        videoSize = naturalSize
        
        // 如果视频有旋转（90/270度），需要交换宽高
        if transform.a == 0 && transform.b == 1.0 && transform.c == -1.0 && transform.d == 0 {
            // 90度旋转
            videoSize = CGSize(width: naturalSize.height, height: naturalSize.width)
        } else if transform.a == 0 && transform.b == -1.0 && transform.c == 1.0 && transform.d == 0 {
            // 270度旋转
            videoSize = CGSize(width: naturalSize.height, height: naturalSize.width)
        }
        return videoSize!
    }
    
    func startUpload() {
        guard let sourceUrl, let image else {
            delegate?.onVideoUploadViewUploadFailed(view: self)
            return
        }
        
        delegate?.onVideoUploadViewStartUpload(view: self)
        if cacheUrl != nil {
            uploadVideo(image: image)
        } else {
            LNVideoCompressor.compressVideo(sourceURL: sourceUrl) { [weak self] url in
                guard let self else {
                    return
                }
                cacheUrl = url
                uploadVideo(image: image)
            }
        }
    }
    
    func cancelUpload() {
        if let curTask {
            LNFileUploader.shared.cancelUpload(taskID: curTask)
        }
    }
    
    func reset() {
        cancelUpload()
        
        image = nil
        videoUrl = nil
        cacheUrl = nil
        imageUrl = nil
        sourceUrl = nil
        curTask = nil
        durationLabel.text = ""
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

extension LNVideoUploadView {
    private func uploadVideo(image: UIImage) {
        guard let cacheUrl,
              let data = try? Data(contentsOf: cacheUrl),
              let imageData = image.jpegData(compressionQuality: 0.7)
        else {
            delegate?.onVideoUploadViewUploadFailed(view: self)
            return
        }
        DispatchQueue.global().async { [weak self] in
            guard let self else { return }
            
            let group = DispatchGroup()
            if videoUrl == nil {
                group.enter()
                let suffix = "\(Int(videoSize?.width ?? 0))x\(Int(videoSize?.height ?? 0)).mp4"
                curTask = LNFileUploader.shared.startUpload(
                    type: .video, fileData: data,
                    suffix: suffix, progressHandler: nil)
                { [weak self] url, err in
                    if let self {
                        curTask = nil
                        if let url {
                            videoUrl = url
                        } else if let err {
                            showToast(err)
                        }
                    }
                    group.leave()
                }
            }
            if imageUrl == nil {
                group.enter()
                let suffix = "\(Int(image.size.width))x\(Int(image.size.height)).jpeg"
                LNFileUploader.shared.startUpload(
                    type: .other, fileData: imageData,
                    suffix: suffix, progressHandler: nil)
                { [weak self] url, err in
                    if let self {
                        if let url {
                            imageUrl = url
                        } else if let err {
                            showToast(err)
                        }
                    }
                    group.leave()
                }
            }
            group.notify(queue: .main) { [weak self] in
                guard let self else { return }
                if let videoUrl, let imageUrl {
                    delegate?.onVideoUploadView(view: self, didUploadVideo: videoUrl, imageUrl: imageUrl)
                } else {
                    delegate?.onVideoUploadViewUploadFailed(view: self)
                }
            }
        }
    }
}

extension LNVideoUploadView {
    private func setupViews() {
        isUserInteractionEnabled = true
        contentMode = .scaleAspectFill
        layer.cornerRadius = 7
        clipsToBounds = true
        
        let cover = UIView()
        cover.backgroundColor = .black.withAlphaComponent(0.2)
        addSubview(cover)
        cover.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        
        let clear = buildClearButton()
        addSubview(clear)
        clear.snp.makeConstraints { make in
            make.top.equalToSuperview().offset(6)
            make.trailing.equalToSuperview().offset(-6)
            make.width.height.equalTo(16)
        }
        
        durationLabel.font = .body_xs
        durationLabel.textColor = .text_1
        addSubview(durationLabel)
        durationLabel.snp.makeConstraints { make in
            make.leading.equalToSuperview().offset(6)
            make.bottom.equalToSuperview().offset(-6)
        }
        
        playButton.setImage(.icVoicePlayWithBlackBg, for: .normal)
        playButton.isUserInteractionEnabled = false
        addSubview(playButton)
        playButton.snp.makeConstraints { make in
            make.center.equalToSuperview()
        }
    }
    
    private func buildClearButton() -> UIView {
        let config = UIImage.SymbolConfiguration(pointSize: 7)
        deleteButton.setImage(.init(systemName: "xmark", withConfiguration: config), for: .normal)
        deleteButton.tintColor = .white
        deleteButton.backgroundColor = .black.withAlphaComponent(0.5)
        deleteButton.layer.cornerRadius = 8
        deleteButton.addAction(UIAction(handler: { [weak self] _ in
            guard let self else { return }
            reset()
            
            delegate?.onVideoUploadViewDidClickDelete(view: self)
        }), for: .touchUpInside)
        
        return deleteButton
    }
}

