import Flutter
import Photos
import UIKit

public class ClassifyPhotoPlugin: NSObject, FlutterPlugin {

  var photoClassifier = ClassifyPhoto()

  public static func register(with registrar: FlutterPluginRegistrar) {
    let channel = FlutterMethodChannel(name: "classify_photo", binaryMessenger: registrar.messenger())
    let instance = ClassifyPhotoPlugin()
    registrar.addMethodCallDelegate(instance, channel: channel)
  }

  public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
    print("iOS: Received method call: \(call.method)")
    switch call.method {
    case "getPhoto":
        self.getPhoto(flutterResult: result)
    case "getStorageInfo":
        getStorageInfo(result: result)
    case "getPlatformVersion":
      result("iOS " + UIDevice.current.systemVersion)
    default:
      result(FlutterMethodNotImplemented)
    }
  }
    
    private class func blankof<T>(type:T.Type) -> T {
        let ptr = UnsafeMutablePointer<T>.allocate(capacity: MemoryLayout<T>.size)
        let val = ptr.pointee
        return val
    }
    
    /// 磁盘总大小
    private class func getTotalDiskSize() -> Int64 {
        var fs = blankof(type: statfs.self)
        if statfs("/var",&fs) >= 0{
            return Int64(UInt64(fs.f_bsize) * fs.f_blocks)
        }
        return -1
    }
    
    private func getStorageInfo(result: @escaping FlutterResult) {
        DispatchQueue.global(qos: .userInitiated).async {
            var storageInfo: [String: Int64] = [:]

            // 获取总容量和可用容量
            if let space = try? FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory()) {
                let totalSpace = ClassifyPhotoPlugin.getTotalDiskSize()
                let freeSpace = space[.systemFreeSize] as? Int64 ?? 0
                storageInfo["totalSpace"] = totalSpace
                storageInfo["freeSpace"] = freeSpace
                storageInfo["usedSpace"] = totalSpace - freeSpace
            }

            // 获取照片占用的空间
            let options = PHFetchOptions()
            let allPhotos = PHAsset.fetchAssets(with: .image, options: options)
            var photoSize: Int64 = 0

            let group = DispatchGroup()
            let queue = DispatchQueue(label: "com.app.photosize", attributes: .concurrent)
            let semaphore = DispatchSemaphore(value: 10) // 限制并发

            allPhotos.enumerateObjects { (asset, index, stop) in
                group.enter()
                semaphore.wait()

                let resources = PHAssetResource.assetResources(for: asset)
                if let resource = resources.first {
                    queue.async {
                        let options = PHAssetResourceRequestOptions()
                        options.isNetworkAccessAllowed = true

                        PHAssetResourceManager.default().requestData(
                            for: resource,
                            options: options,
                            dataReceivedHandler: { data in
                              photoSize += Int64(data.count)
                            },
                            completionHandler: { error in
                              if let error = error {
                                print("Error getting photo size: \(error)")
                              }
                              semaphore.signal()
                              group.leave()
                            }
                        )
                    }
                } else {
                    semaphore.signal()
                    group.leave()
                }
            }

            group.notify(queue: .main) {
                storageInfo["photoSpace"] = photoSize
                result(storageInfo)
            }
        }
    }

  private func getPhoto(flutterResult: @escaping FlutterResult) {

      DispatchQueue.global(qos: .userInitiated).async { [weak self] in
           guard let self = self else { return }

           let fetchOptions = PHFetchOptions()
           let allPhotos = PHAsset.fetchAssets(with: .image, options: fetchOptions)

           photoClassifier.classifyPhotos(
               assets: allPhotos,
               progressHandler: { (stage, progress) in
                   print("Progress: \(stage) - \(progress)")
               },
               completion: { result in
                   var resultData: [[String: Any]] = []
                   let mainGroup = DispatchGroup()
                   
                   // 处理截图
                   mainGroup.enter()
                   self.processPhotoGroup(assets: result.screenshots, groupName: "screenshots", sizeInfo: result.screenshotsSize) { groupData in
                       if !groupData.isEmpty {
                           resultData.append(["group": groupData, "type": "screenshots"])
                       }
                       mainGroup.leave()
                   }
                   
                   // 处理相似照片组
                   for photoGroup in result.similarPhotos {
                       mainGroup.enter()
                       self.processPhotoGroup(assets: photoGroup, groupName: "similar", sizeInfo: result.similarPhotosSize) { groupData in
                           if !groupData.isEmpty {
                               resultData.append(["group": groupData, "type": "similar"])
                           }
                           mainGroup.leave()
                       }
                   }
                   
                   // 处理地点分组
                   for (location, assets) in result.locations {
                       mainGroup.enter()
                       self.processPhotoGroup(assets: assets, groupName: location, sizeInfo: result.locationsSize) { groupData in
                           if !groupData.isEmpty {
                               resultData.append(["group": groupData, "type": "location", "name": location])
                           }
                           mainGroup.leave()
                       }
                   }
                   
                   // 处理人物分组
                   for (person, assets) in result.people {
                       mainGroup.enter()
                       self.processPhotoGroup(assets: assets, groupName: person, sizeInfo: result.peopleSize) { groupData in
                           if !groupData.isEmpty {
                               resultData.append(["group": groupData, "type": "people"])
                           }
                           mainGroup.leave()
                       }
                   }
                   
                   // 处理模糊照片
                   mainGroup.enter()
                   self.processPhotoGroup(assets: result.blurryPhotos, groupName: "blurry", sizeInfo: result.blurryPhotosSize) { groupData in
                       if !groupData.isEmpty {
                           resultData.append(["group": groupData, "type": "blurry"])
                       }
                       mainGroup.leave()
                   }
                   
                   mainGroup.notify(queue: .main) {
                       print("Final result count: \(resultData.count)")
                       flutterResult(resultData)
                   }
               }
           )
       }
  }
    
    // 处理照片组的辅助方法
  private func processPhotoGroup(
    assets: [PHAsset],
    groupName: String,
    sizeInfo: ClassifyPhoto.PhotoSizeInfo,
    completion: @escaping ([String: Any]) -> Void
  ) {
      let photoProcessGroup = DispatchGroup()
      var photosData: [[String: Any]] = []
      
      for asset in assets {
          photoProcessGroup.enter()
          
          let options = PHContentEditingInputRequestOptions()
          options.isNetworkAccessAllowed = true
          
          asset.requestContentEditingInput(with: options) { (input, info) in
              defer { photoProcessGroup.leave() }
              
              if let input = input, let url = input.fullSizeImageURL {
                  let photoInfo: [String: Any] = [
                      "path": url.path,
                      "id": asset.localIdentifier,
                      "width": asset.pixelWidth,
                      "height": asset.pixelHeight,
                      "creationDate": asset.creationDate?.timeIntervalSince1970 ?? 0
                  ]
                  photosData.append(photoInfo)
              }
          }
      }
      
      photoProcessGroup.notify(queue: .main) {
          completion([
              "photos": photosData,
              "totalSize": sizeInfo.totalSize,
              "count": sizeInfo.count
          ])
      }
  }
}
