//
//  CompressViewModel.swift
//  PhoneManager
//
//  Created by edy on 2025/4/3.
//

import Foundation
import Photos


typealias Finished = ([AssetModel])->Void

struct PhotoInfo {
    var localIdentifier : String
    
}

class CompressViewModel{
    /// 校验相册权限
    func checkAndRequestPhotoLibraryPermission() {
        let status = PHPhotoLibrary.authorizationStatus(for: .readWrite)
        switch status {
        case .authorized:
            print("已授权访问相册")
        case .notDetermined:
            PHPhotoLibrary.requestAuthorization(for: .readWrite) { newStatus in
                if newStatus == .authorized {
                    print("用户已授权访问相册")
                    // 在这里执行需要相册权限的操作
                } else {
                    print("用户拒绝授权访问相册")
                    self.showPermissionAlert()
                }
            }
        case .restricted, .denied:
            print("用户未授权或受限访问相册")
            self.showPermissionAlert()
        case .limited:
            self.showPermissionAlert()
        @unknown default:
            print("出现未知的权限状态")
        }
    }
    
    func showPermissionAlert() {
        let alertController = UIAlertController(
            title: "权限请求",
            message: "为了使用此功能，需要访问您的相册。请在设置中授予相册访问权限。",
            preferredStyle: .alert
        )
        let settingsAction = UIAlertAction(title: "前往设置", style: .default) { _ in
            if let settingsURL = URL(string: UIApplication.openSettingsURLString) {
                UIApplication.shared.open(settingsURL, options: [:], completionHandler: nil)
            }
        }
        let cancelAction = UIAlertAction(title: "取消", style: .cancel, handler: nil)
        alertController.addAction(settingsAction)
        alertController.addAction(cancelAction)
        if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
           let window = windowScene.windows.first {
            window.rootViewController?.present(alertController, animated: true, completion: nil)
        }
    }
    
    
    
    /// 获取相册所有图片
    /// - Returns: 图片信息
    func getAllPhotosToAssets(sortType: ResouceSortType, assetType : CompressType,_ finished: @escaping Finished){
        var models : [AssetModel] = []
        PhotoManager.shared.reloadTrashAndKeep()
        if assetType == .compressPhoto {
            models = PhotoManager.shared.filterOtherModels +  PhotoManager.shared.filterScreenShotModels
        }else {
            models = PhotoManager.shared.filterVideoModels
        }
        // 默认按照文件大小排序
        if sortType == .largest {
            finished(models.sorted { $0.assetSize > $1.assetSize })
        }else if sortType == .smallest {
            finished(models.sorted { $0.assetSize < $1.assetSize })
        }else if sortType == .latest {
            finished(models.sorted { $0.createDate > $1.createDate })
        }else{
            finished(models.sorted { $0.createDate < $1.createDate })
        }
    }

    
    /// 视频压缩
    /// - Parameters:
    ///   - assetIdentifiers: 视频文件标识
    ///   - quality: 压缩质量
    ///   - progress: 进度回调
    ///   - completion: 完成回调
    static func compressVideos(
        models: [AssetModel],
        quality: Float,
        progress: @escaping (Float) -> Void,
        completion: @escaping ([URL?], [Error?]) -> Void
    ) {
        VideoCompressor.compressVideos(models: models, quality: quality, progress: progress, completion: completion)
    }
    
    /// 压缩多张图片
    /// - Parameters:
    ///   - assets: 图片集合
    ///   - compressionQuality: 图片质量
    ///   - progressHandler: 进度
    ///   - completion: 完成
    func compress(assets: [AssetModel], compressionQuality : CGFloat, progressHandler: @escaping (Float) -> Void, completion: @escaping ([Data?], [Error?]) -> Void) {
        
        var compressedDataArray: [Data?] = Array(repeating: nil, count: assets.count)
        var errorArray: [Error?] = Array(repeating: nil, count: assets.count)
        var completedCount = 0
        let totalCount = assets.count
        
        for (index, model) in assets.enumerated() {
            let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [model.localIdentifier], options: nil)
            compressSingleAsset(fetchResult.firstObject!,compressionQuality) { (progress) in
                let singleProgress = Float(completedCount) / Float(totalCount) + progress / Float(totalCount)
                progressHandler(singleProgress)
            } completion: { (compressedData, error) in
                compressedDataArray[index] = compressedData
                errorArray[index] = error
                completedCount += 1
                
                if completedCount == totalCount {
                    completion(compressedDataArray, errorArray)
                }
            }
        }
    }
    
    private func compressSingleAsset(_ asset: PHAsset,_ compressionQuality : CGFloat,  progress: @escaping (Float) -> Void, completion: @escaping (Data?, Error?) -> Void) {
        let options = PHImageRequestOptions()
        options.isSynchronous = false
        // 设置为原图片
        options.version = .original
        PHImageManager.default().requestImageDataAndOrientation(for: asset, options: options) { (imageData, _, _, error) in
            guard let originalData = imageData else {
                completion(nil, nil)
                return
            }
            
            let totalSize = originalData.count
            var processedSize = 0
            self.compressData(originalData, compressionQuality: compressionQuality) { (progressValue) in
                processedSize = Int(Float(totalSize) * progressValue)
                let currentProgress = Float(processedSize) / Float(totalSize)
                progress(currentProgress)
            } completion: { (compressedData, error) in
                completion(compressedData, error)
            }
        }
    }
    
    private func compressData(_ data: Data,
                             compressionQuality: CGFloat,
                             progress: @escaping (Float) -> Void,
                             completion: @escaping (Data?, Error?) -> Void) {
        DispatchQueue.global(qos: .userInitiated).async {
            // 错误处理闭包
            func completeOnMain(error: Error? = nil, data: Data? = nil) {
                DispatchQueue.main.async {
                    completion(data, error)
                }
            }
            
            // 验证输入数据
            guard let image = UIImage(data: data) else {
                completeOnMain(error: NSError(domain: "ImageError", code: -1,
                                  userInfo: [NSLocalizedDescriptionKey: "Invalid image data"]))
                return
            }
            
            let originalSize = data.count
            let targetSize = max(Int(CGFloat(originalSize) * compressionQuality), 1024)
            var currentImage = image
            var currentBestData: Data?
            
            // 进度配置
            let maxIterations = 5
            let qualitySteps: [CGFloat] = [0.9, 0.7, 0.5, 0.3, 0.2]
            var currentIteration = 0
            
            // 递归压缩方法
            func tryCompress() {
                guard currentIteration < maxIterations else {
                    // 最终返回最佳结果或最后一次尝试
                    completeOnMain(data: currentBestData ?? currentImage.jpegData(compressionQuality: 0.1))
                    return
                }
                
                // 当前轮次的压缩质量
                let currentQuality = qualitySteps[currentIteration]
                var compressedData: Data?
                
                // 尝试生成压缩数据
                autoreleasepool {
                    compressedData = currentImage.jpegData(compressionQuality: currentQuality)
                }
                
                guard let validData = compressedData else {
                    completeOnMain(error: NSError(domain: "CompressionError", code: -2,
                                    userInfo: [NSLocalizedDescriptionKey: "Compression failed"]))
                    return
                }
                
                // 更新最佳结果
                if validData.count <= targetSize && validData.count > (currentBestData?.count ?? 0) {
                    currentBestData = validData
                }
                
                // 更新进度（每轮20%）
                DispatchQueue.main.async {
                    progress(Float(currentIteration + 1) / Float(maxIterations))
                }
                
                // 检查是否达标
                if validData.count <= targetSize {
                    completeOnMain(data: validData)
                    return
                }
                
                // 未达标时调整尺寸
                let scaleFactor = sqrt(Double(targetSize) / Double(validData.count))
                currentImage = self.resizeImage(currentImage, scaleFactor: CGFloat(scaleFactor))
                currentIteration += 1
                
                // 继续下一轮压缩
                tryCompress()
            }
            
            // 开始压缩流程
            tryCompress()
        }
    }

    // 图片尺寸调整方法保持不变
    private func resizeImage(_ image: UIImage, scaleFactor: CGFloat) -> UIImage {
        let newSize = CGSize(
            width: max(image.size.width * scaleFactor, 1),
            height: max(image.size.height * scaleFactor, 1)
        )
        let format = UIGraphicsImageRendererFormat()
        format.scale = 1.0
        format.opaque = true
        
        let renderer = UIGraphicsImageRenderer(size: newSize, format: format)
        return renderer.image { _ in
            image.draw(in: CGRect(origin: .zero, size: newSize))
        }
    }
    
    // 通过identifier获取image
    func getImageFromAssetIdentifier(identifier: String, completion: @escaping (UIImage?) -> Void) {
        let fetchOptions = PHFetchOptions()
        let assets = PHAsset.fetchAssets(withLocalIdentifiers: [identifier], options: fetchOptions)
        
        guard let asset = assets.firstObject else {
            completion(nil)
            return
        }
        
        let imageManager = PHCachingImageManager()
        let options = PHImageRequestOptions()
        options.isSynchronous = false
        options.deliveryMode = .opportunistic
        options.isNetworkAccessAllowed = true
        
        imageManager.requestImage(for: asset, targetSize: CGSize(width: 400, height: 400), contentMode: .aspectFill, options: options) { (image, _) in
            completion(image)
        }
    }
    
}

