//
//  TSImageCompress.swift
//  Pods
//
//  Created by 100Years on 2025/4/15.
//

import UIKit

// MARK: - UIImage 扩展（Alpha 通道检测和缩放）
public extension UIImage {
    /// 检查图片是否有 Alpha 通道（透明度）
    func hasAlphaChannel() -> Bool {
        guard let cgImage = self.cgImage else { return false }
        let alphaInfo = cgImage.alphaInfo
        return alphaInfo == .first || alphaInfo == .last || alphaInfo == .premultipliedFirst || alphaInfo == .premultipliedLast
    }
    
    /// 按比例缩放图片
    func resized(withScaleFactor scaleFactor: CGFloat) -> UIImage {
        let newSize = CGSize(width: size.width * scaleFactor, height: size.height * scaleFactor)
        let renderer = UIGraphicsImageRenderer(size: newSize)
        return renderer.image { _ in
            self.draw(in: CGRect(origin: .zero, size: newSize))
        }
    }
}

public class TSImageCompress {

    // MARK: - 核心压缩方法
    public static func compressImageToTargetSize(
        _ image: UIImage,
        targetSizeKB: Int,
        preserveTransparency: Bool
    ) -> Data? {
        let targetBytes = targetSizeKB * 1024
        let hasAlpha = image.hasAlphaChannel()
        let usePNG = preserveTransparency && hasAlpha

        if usePNG {
            let compressPNGImage = compressPNGImage(image, targetBytes: targetBytes)
            if let compressedData = compressPNGImage {
//                saveData(compressedData: compressedData)
                print("PNG 压缩后大小: \(compressedData.count / 1024)KB")
            }
            return compressPNGImage
        } else {
            let compressJPEGImage = compressJPEGImage(image, targetBytes: targetBytes)
            if let compressJPEGImage = compressJPEGImage {
//                saveData(compressedData: compressJPEGImage)
                print("JPEG 压缩后大小: \(compressJPEGImage.count / 1024)KB")
            }
            return compressJPEGImage
        }
    }

    // MARK: - PNG 压缩逻辑（调整尺寸）
    static private func compressPNGImage(_ image: UIImage, targetBytes: Int) -> Data? {
        var currentImage = image
        var currentData = currentImage.pngData()
        var currentBytes = currentData?.count ?? 0
        
        // 如果已经满足目标大小，直接返回
        guard currentBytes > targetBytes else { return currentData }
        
        var scaleFactor: CGFloat = 0.9
        let minScaleFactor: CGFloat = 0.1
        
        while scaleFactor >= minScaleFactor {
            let scaledImage = currentImage.resized(withScaleFactor: scaleFactor)
            guard let newData = scaledImage.pngData() else { break }
            let newBytes = newData.count
            
            if newBytes <= targetBytes {
                return newData // 达到目标
            }
            
            if newBytes >= currentBytes {
                break // 无法继续优化
            }
            
            currentImage = scaledImage
            currentData = newData
            currentBytes = newBytes
            scaleFactor -= 0.1
        }
        
        return currentBytes <= targetBytes ? currentData : nil
    }

    // MARK: - JPEG 压缩逻辑（先调质量，后调尺寸）
    static private func compressJPEGImage(_ image: UIImage, targetBytes: Int) -> Data? {
        var compressionQuality: CGFloat = 1.0
        var currentImage = image
        var currentData = currentImage.jpegData(compressionQuality: compressionQuality)
        var currentBytes = currentData?.count ?? 0
        
        // 第一步：降低 JPEG 质量
        while currentBytes > targetBytes && compressionQuality > 0.1 {
            compressionQuality -= 0.1
            currentData = currentImage.jpegData(compressionQuality: compressionQuality)
            currentBytes = currentData?.count ?? 0
        }
        
        guard currentBytes > targetBytes else { return currentData }
        
        // 第二步：缩小尺寸
        var scaleFactor: CGFloat = 0.9
        let minScaleFactor: CGFloat = 0.1
        
        while scaleFactor >= minScaleFactor {
            let scaledImage = currentImage.resized(withScaleFactor: scaleFactor)
            guard let newData = scaledImage.jpegData(compressionQuality: compressionQuality) else { break }
            let newBytes = newData.count
            
            if newBytes <= targetBytes {
                return newData // 达到目标
            }
            
            if newBytes >= currentBytes {
                break // 无法继续优化
            }
            
            currentImage = scaledImage
            currentData = newData
            currentBytes = newBytes
            scaleFactor -= 0.1
        }
        
        return currentBytes <= targetBytes ? currentData : nil
    }
}


extension TSImageCompress {
    
    static func saveData(compressedData:Data){
        // 写入到沙盒的 "Images" 子目录
          let fileName = "compressed_\(Date().timeIntervalSince1970).jpg"
          if let fileURL = writeDataToSandbox(data: compressedData, fileName: fileName, subDirectory: "Images") {
              print("文件已保存至: \(fileURL.path)")
              
              // 可选：读取文件验证
              if let savedData = try? Data(contentsOf: fileURL) {
                  print("读取文件大小: \(savedData.count / 1024)KB")
              }
          }
    }
    
    static func getDocumentsDirectory() -> URL {
        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        return paths[0] // 返回第一个路径（通常唯一）
    }
    
    static func writeDataToSandbox(data: Data, fileName: String, subDirectory: String? = nil) -> URL? {
        let baseDirectory: URL
        
        // 1. 确定基础目录（默认 Documents）
        baseDirectory = getDocumentsDirectory()
        
        // 2. 拼接子目录（如果存在）
        var targetDirectory = baseDirectory
        if let subDir = subDirectory {
            targetDirectory = baseDirectory.appendingPathComponent(subDir)
        }
        
        // 3. 创建子目录（如果不存在）
        do {
            try FileManager.default.createDirectory(at: targetDirectory, withIntermediateDirectories: true, attributes: nil)
        } catch {
            print("创建目录失败: \(error.localizedDescription)")
            return nil
        }
        
        // 4. 拼接最终文件路径
        let fileURL = targetDirectory.appendingPathComponent(fileName)
        
        // 5. 写入数据
        do {
            try data.write(to: fileURL)
//            print("文件写入成功: \(fileURL.path)")
            return fileURL
        } catch {
            print("写入文件失败: \(error.localizedDescription)")
            return nil
        }
    }

}
