//
//  LivePhotoTool.swift
//  TSLiveWallpaper
//
//  Created by 100Years on 2024/12/31.
//

import Foundation
import AVFoundation
import UIKit
import Photos

class LivePhotoConverter {
    
    static func convertVideo(
        _ videoURL: URL,
        imageURL:URL? = nil,
        completion: @escaping (Bool, URL?, URL?, String?) -> Void
    ) {
        print("Start converting...")
        
        guard let metaURL = Bundle.main.url(forResource: "metadata", withExtension: "mov") else {
//        guard let metaURL = Bundle.main.url(forResource: "output", withExtension: "mov") else {
            completion(false, nil, nil, "Metadata file not found")
            return
        }
        
        
        let fileManager = FileManager.default
        let eidtVideoPathURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!.appendingPathComponent("livePhoto").appendingPathComponent("editVideo")

        
        
        let documentPath = eidtVideoPathURL.path
        let durationPath = "\(documentPath)/duration.mp4"
        let acceleratePath = "\(documentPath)/accelerate.mp4"
        let resizePath = "\(documentPath)/resize.mp4"
        
        let destinationDirectory = eidtVideoPathURL
        // 如果目标文件夹不存在，创建文件夹
        if !fileManager.fileExists(atPath: destinationDirectory.path) {
            do {
                try fileManager.createDirectory(at: destinationDirectory, withIntermediateDirectories: true, attributes: nil)
                debugPrint("创建文件夹成功")
            } catch {
                debugPrint("尝试创建文件夹失败: \(error.localizedDescription)")
            }
        }
        
        try? FileManager.default.removeItem(atPath: durationPath)
        try? FileManager.default.removeItem(atPath: acceleratePath)
        try? FileManager.default.removeItem(atPath: resizePath)
        
        let asset = AVURLAsset(url: videoURL)
        let targetDuration = CMTimeGetSeconds(asset.duration)
//        let videoSize = asset.tracks(withMediaType: .video).first?.naturalSize ?? CGSize(width: 1080, height: 1920)
//        let videoSize = CGSize(width: 1080, height: 1920)
        
        let videoSize = CGSize(width: 1080, height: 1920)
//        let livePhotoDuration = CMTimeMake(value: 550, timescale: 600)
        let livePhotoDuration = CMTimeMake(value: 550, timescale: 600)
        let assetIdentifier = UUID().uuidString
        let finalPath = resizePath
        let converter = Converter4Video(path: finalPath)
        
        converter.durationVideo(at: videoURL.path, outputPath: durationPath, targetDuration: targetDuration) { success, error in
            guard success else {
                completion(false, nil, nil, error?.localizedDescription)
                return
            }
            
            converter.accelerateVideo(at: durationPath, to: livePhotoDuration, outputPath: acceleratePath) { success, error in
                guard success else {
                    completion(false, nil, nil, error?.localizedDescription)
                    return
                }

                converter.resizeVideo(at: acceleratePath, outputPath: resizePath, outputSize: videoSize) { success, error in
                    guard success else {
                        completion(false, nil, nil, error?.localizedDescription)
                        return
                    }

                    let picturePath = "\(documentPath)/live.heic"
                    let videoPath = "\(documentPath)/live.mov"
                    
                    try? FileManager.default.removeItem(atPath: picturePath)
                    try? FileManager.default.removeItem(atPath: videoPath)
                    
                    let asset = AVURLAsset(url:URL(fileURLWithPath: finalPath))
                    var image:UIImage? = nil
                    if let imageURL = imageURL {
                        image = UIImage(contentsOfFile: imageURL.path)
                    }else{
                        if let imageData = self.generateKeyPhoto(from: asset) {
                            image = UIImage(data: imageData)
                        }
                    }
                    
                    guard let image = image else {
                        completion(false, nil, nil, "image nil")
                        return
                    }
                    
                    let imageConverter = Converter4Image(image:image)
                    imageConverter.write(dest: picturePath, assetIdentifier: assetIdentifier)
                    converter.write(dest: videoPath, assetIdentifier: assetIdentifier, metaURL: metaURL) { success, error in
                        guard success else {
                            completion(false, nil, nil, error?.localizedDescription)
                            return
                        }
                        
                        let photoURL = URL(fileURLWithPath: picturePath)
                        let pairedVideoURL = URL(fileURLWithPath: videoPath)
                        
                        debugPrint("picturePath=\(picturePath)")
                        debugPrint("videoPath=\(videoPath)")
                        
                        DispatchQueue.main.async {
                            completion(success, photoURL, pairedVideoURL, error?.localizedDescription)
                        }
                    }
                }
            }
        }
    }
    
    
    
//    static func convertVideo(
//        _ videoURL: URL,
//        imageURL:URL? = nil,
//        completion: @escaping (Bool, URL?, URL?, String?) -> Void
//    ) {
//        print("Start converting...")
//        
//        guard let metaURL = Bundle.main.url(forResource: "metadata", withExtension: "mov") else {
//            completion(false, nil, nil, "Metadata file not found")
//            return
//        }
//        
//        
//        let fileManager = FileManager.default
//        let eidtVideoPathURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!.appendingPathComponent("livePhoto").appendingPathComponent("editVideo")
//
//        
//        
//        let documentPath = eidtVideoPathURL.path
//        let durationPath = "\(documentPath)/duration.mp4"
//        let acceleratePath = "\(documentPath)/accelerate.mp4"
//        let resizePath = "\(documentPath)/resize.mp4"
//        
//        let destinationDirectory = eidtVideoPathURL
//        // 如果目标文件夹不存在，创建文件夹
//        if !fileManager.fileExists(atPath: destinationDirectory.path) {
//            do {
//                try fileManager.createDirectory(at: destinationDirectory, withIntermediateDirectories: true, attributes: nil)
//                debugPrint("创建文件夹成功")
//            } catch {
//                debugPrint("尝试创建文件夹失败: \(error.localizedDescription)")
//            }
//        }
//        
//        try? FileManager.default.removeItem(atPath: durationPath)
//        try? FileManager.default.removeItem(atPath: acceleratePath)
//        try? FileManager.default.removeItem(atPath: resizePath)
//        
//        let asset = AVURLAsset(url: videoURL)
//        let targetDuration = CMTimeGetSeconds(asset.duration)
////        let videoSize = asset.tracks(withMediaType: .video).first?.naturalSize ?? CGSize(width: 1080, height: 1920)
//        let videoSize = CGSize(width: 1080, height: 1920)
//        let livePhotoDuration = CMTimeMake(value: 550, timescale: 600)
//        let assetIdentifier = UUID().uuidString
//        let finalPath = resizePath
//        let converter = Converter4Video(path: finalPath)
//        
//        converter.durationVideo(at: videoURL.path, outputPath: durationPath, targetDuration: targetDuration) { success, error in
//            guard success else {
//                completion(false, nil, nil, error?.localizedDescription)
//                return
//            }
//            
//            converter.accelerateVideo(at: durationPath, to: livePhotoDuration, outputPath: acceleratePath) { success, error in
//                guard success else {
//                    completion(false, nil, nil, error?.localizedDescription)
//                    return
//                }
//                
//                converter.resizeVideo(at: acceleratePath, outputPath: resizePath, outputSize: videoSize) { success, error in
//                    guard success else {
//                        completion(false, nil, nil, error?.localizedDescription)
//                        return
//                    }
//
//                    let picturePath = "\(documentPath)/live.heic"
//                    let videoPath = "\(documentPath)/live.mov"
//                    
//                    try? FileManager.default.removeItem(atPath: picturePath)
//                    try? FileManager.default.removeItem(atPath: videoPath)
//                    
//                    let asset = AVURLAsset(url:URL(fileURLWithPath: finalPath))
//                    var image:UIImage? = nil
//                    if let imageURL = imageURL {
//                        image = UIImage(contentsOfFile: imageURL.path)
//                    }else{
//                        if let imageData = self.generateKeyPhoto(from: asset) {
//                            image = UIImage(data: imageData)
//                        }
//                    }
//                    
//                    guard let image = image else {
//                        completion(false, nil, nil, "image nil")
//                        return
//                    }
//                    
//                    let imageConverter = Converter4Image(image:image)
//                    imageConverter.write(dest: picturePath, assetIdentifier: assetIdentifier)
//                    converter.write(dest: videoPath, assetIdentifier: assetIdentifier, metaURL: metaURL) { success, error in
//                        guard success else {
//                            completion(false, nil, nil, error?.localizedDescription)
//                            return
//                        }
//                        
//                        let photoURL = URL(fileURLWithPath: picturePath)
//                        let pairedVideoURL = URL(fileURLWithPath: videoPath)
//                        
//                        debugPrint("picturePath=\(picturePath)")
//                        debugPrint("videoPath=\(videoPath)")
//                        
//                        DispatchQueue.main.async {
//                            completion(success, photoURL, pairedVideoURL, error?.localizedDescription)
//                        }
//                    }
//                }
//            }
//        }
//    }
    

    private static func generateKeyPhoto(from videoAsset: AVAsset) -> Data? {
        var percent:Float = 0.5
        if let stillImageTime = videoAsset.stillImageTime() {
            percent = Float(stillImageTime.value) / Float(videoAsset.duration.value)
        }
        guard let imageFrame = videoAsset.getAssetFrame(percent: percent) else { return nil }
        guard let jpegData = imageFrame.jpegData(compressionQuality: 1.0) else { return nil }
        return jpegData
    }
    
    static func livePhotoRequest(videoURL:URL,imageURL:URL,completion: @escaping (PHLivePhoto?) -> Void){
        _ = PHLivePhoto.request(withResourceFileURLs: [videoURL, imageURL], placeholderImage: nil, targetSize: CGSize.zero, contentMode: PHImageContentMode.aspectFill, resultHandler: { (livePhoto: PHLivePhoto?, info: [AnyHashable : Any]) -> Void in
            if let isDegraded = info[PHLivePhotoInfoIsDegradedKey] as? Bool, isDegraded {
                return
            }
            DispatchQueue.main.async {
                completion(livePhoto)
            }
        })
    }
    

    static func saveToLibrary(videoURL:URL,imageURL:URL,completion: @escaping (Bool) -> Void){
        PHPhotoLibrary.shared().performChanges({
            let creationRequest = PHAssetCreationRequest.forAsset()
            let options = PHAssetResourceCreationOptions()
            creationRequest.addResource(with: PHAssetResourceType.pairedVideo, fileURL: videoURL, options: options)
            creationRequest.addResource(with: PHAssetResourceType.photo, fileURL: imageURL, options: options)
        }, completionHandler: { (success, error) in
            if error != nil {
                print(error as Any)
            }
            DispatchQueue.main.async {
                completion(success)
            }
        })
    }
    
}

