//
//  PhotoDuplicateManager.swift
//  CleanPhoto
//
//  Created by edy on 2025/5/8.
//

import Foundation
import Photos
import UIKit


// 移除顶层的 @MainActor
class PhotoDuplicateManager: @unchecked Sendable {
    static let shared = PhotoDuplicateManager()
    private let stateManager = PhotoDuplicateStateManager()  // 使用新的状态管理器
    private init() {}
    
    // MARK: - 配置参数
    private let timeWindowInSeconds: TimeInterval = 600 // 10分钟时间窗口
    
    // 文件路径
    private var timeGroupsPath: String {
        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        return paths[0].appendingPathComponent("DuplicateTimeGroups.json").path
    }
    
    private var duplicateGroupsPath: String {
        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        return paths[0].appendingPathComponent("DuplicateGroups.json").path
    }
    
    private var currentTask: Task<Void, Error>?
    
    // 最新照片时间戳存储key
    private let latestPhotoTimeKey = "DuplicateLatestPhotoTimestamp"
    
    func findDuplicateAssets(in assets: [PHAsset],
                          mediaType: MediaType = .photo,
                          loacalHandler: (([[AssetModel]]) -> Void)?,
                          progressHandler: (([AssetModel]) -> Void)?,
                             completionHandler: (([[AssetModel]]) -> Void)?) {
        
 
        Task.detached(priority: .background) { [weak self] in
            guard let self = self else { return }
            // 1. 加载本地数据
            await loadStoredData()
            print("本地数据加载完成")
            
            // 2. 通知已缓存的结果
            let cachedGroups = await loadSimilarGroups() //stateManager.getAllDuplicateGroups()
            print("通知已缓存的结果", cachedGroups.count)
            await MainActor.run {
                let groups = cachedGroups.map{$0.assets}
                loacalHandler?(groups)
            }
            //返回本地数据后 清空
            await stateManager.removeGroup()
            // 4. 按特征预分组（分辨率、时间、文件大小）
            var featureGroups: [[PHAsset]] = []
            var tempGroups: [String: [PHAsset]] = [:] // 临时用于分组
            
            // 第一次遍历：收集相同特征的资源
            for asset in assets {
                // 创建特征键（分辨率+创建时间+文件大小）
                let resolution = "\(asset.pixelWidth)x\(asset.pixelHeight)"
                // let createTime = asset.creationDate?.timeIntervalSince1970 ?? 0
                let fileSize = await getAssetSize(asset: asset)
                let featureKey = "\(resolution)_\(fileSize)"
                
                if tempGroups[featureKey] == nil {
                    tempGroups[featureKey] = []
                }
                tempGroups[featureKey]?.append(asset)
            }
            
            // 第二次遍历：只保留有多个资源的组
            featureGroups = tempGroups.values.filter { $0.count > 1 }
            
            // 如果没有需要处理的组，直接返回缓存结果
            if featureGroups.isEmpty {
                let total = cachedGroups.map { $0.assets }
                await MainActor.run {
                    completionHandler?(total)
                }
                return
            }
            
            let maxConcurrency = 2 // 最大并发数
            let batchSize = max(1, featureGroups.count / maxConcurrency)
            
            for batchIndex in stride(from: 0, to: featureGroups.count, by: batchSize) {
                let endIndex = min(batchIndex + batchSize, featureGroups.count)
                let batch = Array(featureGroups[batchIndex..<endIndex])
                
                await withTaskGroup(of: Void.self) { group in
                    for assets in batch {
                        group.addTask { [weak self] in
                            guard let self = self else { return }
                            
                            // 只需要计算phash值并比较
                            var hashGroups: [String: [PHAsset]] = [:]
                            
                            for asset in assets {
                                if let hash = await self.getOrCalculateHash(for: asset) {
                                    if hashGroups[hash] == nil {
                                        hashGroups[hash] = []
                                    }
                                    hashGroups[hash]?.append(asset)
                                }
                            }
                            
                            // 找出phash值相同的组
                            let duplicateGroups = hashGroups.values.filter { $0.count > 1 }
                            
                            // 处理找到的重复组
                            for duplicateGroup in duplicateGroups {
                                let groupId = UUID().uuidString
                                let assetModels = await self.createAssetModels(from: duplicateGroup)
                                
                                // 通知进度
                                await MainActor.run {
                                    progressHandler?(assetModels)
                                }
                                
                                // 保存重复组
                                await self.stateManager.appendDuplicateGroup(
                                    SimilarGroupModel(groupId: groupId, assets: assetModels)
                                )
                                
                                if await self.stateManager.shouldSavePendingGroups() {
                                    await self.savePendingDuplicateGroups()
                                }
                            }
                        }
                    }
                }
            }
            
            // 6. 完成处理
            if await !stateManager.getPendingDuplicateGroups().isEmpty {
                await self.savePendingDuplicateGroups()
            }
            
            let allGroups = await loadSimilarGroups() //stateManager.getAllDuplicateGroups()
            await MainActor.run {
                print("执行完毕")
                completionHandler?(allGroups.map { $0.assets })
            }
        }
    
    }

    func getAssetSize(asset: PHAsset) async -> Int64 {
        // 先尝试从缓存获取
        if let cachedSize = await AssetSizeCache.shared.getSize(for: asset) {
            return cachedSize
        }
        
        // 如果缓存中没有，则计算大小
        if let resource = PHAssetResource.assetResources(for: asset).first,
           let size = resource.value(forKey: "fileSize") as? Int64 {
            // 将计算结果存入缓存
            await AssetSizeCache.shared.setSize(size, for: asset)
            return size
        }
        
        return 0
    }
    
    private func createAssetModels(from assets: [PHAsset]) async -> [AssetModel] {
        return await withTaskGroup(of: AssetModel.self) { modelGroup in
            var models: [AssetModel] = []
            
            for asset in assets {
                modelGroup.addTask {
                    let size = await self.getAssetSize(asset: asset)
                    return AssetModel(
                        localIdentifier: asset.localIdentifier,
                        assetSize: Double(size),
                        createDate: asset.creationDate ?? Date(),
                        mediaType: 1
                    )
                }
            }
            
            for await model in modelGroup {
                models.append(model)
            }
            return models
        }
    }
}

// MARK: - 存储相关方法
extension PhotoDuplicateManager {
    
    private func loadStoredData() async {
        var loadedDuplicateGroups: [SimilarGroupModel] = []
        
        if let data = try? Data(contentsOf: URL(fileURLWithPath: duplicateGroupsPath)),
           let groups = try? JSONDecoder().decode([SimilarGroupModel].self, from: data) {
            loadedDuplicateGroups = groups
        }
        
        await stateManager.loadStoredData(duplicateGroups: loadedDuplicateGroups)
    }
    
    private func savePendingDuplicateGroups() async {
          await stateManager.savePendingGroups()
          if let data = try? JSONEncoder().encode(await loadSimilarGroups()) {
              try? data.write(to: URL(fileURLWithPath: duplicateGroupsPath))
          }
    }
    
    private func loadSimilarGroups() async -> [SimilarGroupModel] {
        let groups = await stateManager.getAllDuplicateGroups()
        // 验证资源有效性
        return groups.map { group in
            var validAssets = group.assets
            validAssets.removeAll { asset in
                let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [asset.localIdentifier], options: nil)
                return fetchResult.firstObject == nil
            }
            return SimilarGroupModel(groupId: group.groupId, assets: validAssets)
        }.filter { $0.assets.count > 1}
    }
    
    // 移除本地文件资源
    func removeLocalFileWithIds(for ids:[String]) async{
        await stateManager.deleteData(for: ids)
        
        // 保存到文件
        if let data = try? JSONEncoder().encode(await loadSimilarGroups()) {
            try? data.write(to: URL(fileURLWithPath: duplicateGroupsPath))
        }
    }
}

// MARK: - Hash计算相关方法
extension PhotoDuplicateManager {
    private func getOrCalculateHash(for asset: PHAsset) async -> String? {
        if let cachedHash = await stateManager.getCachedHash(for: asset.localIdentifier) {
            return cachedHash
        }
        
        if let cachedImage = await stateManager.getCachedImage(for: asset.localIdentifier) {
            let hash = calculateImageHash(cachedImage)
            await stateManager.setCachedHash(hash, for: asset.localIdentifier)
            return hash
        }
        
        let options = PHImageRequestOptions()
        options.version = .original
        let targetSize = CGSize(width: 32, height: 32)
        
        return await withCheckedContinuation { continuation in
            PHImageManager.default().requestImage(for: asset, targetSize: targetSize, contentMode: .aspectFit, options: options) { [weak self] image, _ in
                if let image = image, let self = self {
                    let hash = self.calculateImageHash(image)
                    Task {
                        await self.stateManager.setCachedImage(image, for: asset.localIdentifier)
                        await self.stateManager.setCachedHash(hash, for: asset.localIdentifier)
                    }
                    continuation.resume(returning: hash)
                } else {
                    continuation.resume(returning: nil)
                }
            }
        }
    }
    
    private func calculateImageHash(_ image: UIImage) -> String {
        guard let cgImage = image.cgImage else { return "" }
        let ciImage = CIImage(cgImage: cgImage)
        
        guard let filter = CIFilter(name: "CIPhotoEffectNoir"),
              let outputImage = filter.outputImage else {
            return ""
        }
        
        filter.setValue(ciImage, forKey: kCIInputImageKey)
        
        let context = CIContext()
        guard let scaledImage = context.createCGImage(outputImage, from: outputImage.extent),
              let pixelData = UIImage(cgImage: scaledImage).cgImage?.dataProvider?.data,
              let data = CFDataGetBytePtr(pixelData) else {
            return ""
        }
        
        var pixels = Array(repeating: UInt8(0), count: 1024)
        for i in 0..<32 {
            for j in 0..<32 {
                let pixelIndex = (i * 32 + j) * 4
                let gray = UInt8(
                    0.299 * Double(data[pixelIndex]) +
                    0.587 * Double(data[pixelIndex + 1]) +
                    0.114 * Double(data[pixelIndex + 2])
                )
                pixels[i * 32 + j] = gray
            }
        }
        
        let average = UInt8(pixels.reduce(0, { UInt32($0) + UInt32($1) }) / UInt32(pixels.count))
        return pixels.map { $0 > average ? "1" : "0" }.joined()
    }
    
}



