import Flutter
import StoreKit
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 "getExifInfo":
        guard let args = call.arguments as? [String: Any],
              let filePath = args["filePath"] as? String else {
            result(FlutterError(
                code: "INVALID_ARGUMENTS",
                message: "Missing filePath parameter",
                details: nil
            ))
            return
        }
        getExifInfo(filePath: filePath, completion: result)
    case "getPhotosSize":
        guard let args = call.arguments as? [String: Any],
              let assetIds = args["assetIds"] as? [String] else {
            result(FlutterError(
                code: "INVALID_ARGUMENTS",
                message: "Missing filePath parameter",
                details: nil
            ))
            return
        }
        calculatePhotosSize(assetIds: assetIds, completion: 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
          ])
      }
  }
    
    private func getExifInfo(filePath: String, completion: @escaping FlutterResult) {
            // 创建文件 URL
            let fileURL: URL
            if filePath.starts(with: "file://") {
                guard let url = URL(string: filePath) else {
                    print("Invalid URL string: \(filePath)")
                    completion([:])
                    return
                }
                fileURL = url
            } else {
                fileURL = URL(fileURLWithPath: filePath)
            }
            
            // 检查文件是否存在
            guard FileManager.default.fileExists(atPath: fileURL.path) else {
                print("File does not exist at path: \(fileURL.path)")
                completion([:])
                return
            }
        
            // 创建图片源
            guard let imageSource = CGImageSourceCreateWithURL(fileURL as CFURL, nil) else {
                print("Failed to create image source for path: \(fileURL.path)")
                completion([:])
                return
            }
            
            var exifInfo: [String: Any] = [:]
            
            // 获取所有元数据
            if let imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) as? [String: Any] {
                // EXIF 数据
                if let exif = imageProperties[kCGImagePropertyExifDictionary as String] as? [String: Any] {
                    exifInfo["aperture"] = exif[kCGImagePropertyExifFNumber as String]
                    exifInfo["exposureTime"] = exif[kCGImagePropertyExifExposureTime as String]
                    exifInfo["iso"] = exif[kCGImagePropertyExifISOSpeedRatings as String]
                    exifInfo["focalLength"] = exif[kCGImagePropertyExifFocalLength as String]
                    exifInfo["dateTimeOriginal"] = exif[kCGImagePropertyExifDateTimeOriginal as String]
                }
                
                // TIFF 数据
                if let tiff = imageProperties[kCGImagePropertyTIFFDictionary as String] as? [String: Any] {
                    exifInfo["make"] = tiff[kCGImagePropertyTIFFMake as String]
                    exifInfo["model"] = tiff[kCGImagePropertyTIFFModel as String]
                }
                
                // GPS 数据
                if let gps = imageProperties[kCGImagePropertyGPSDictionary as String] as? [String: Any] {
                    exifInfo["latitude"] = gps[kCGImagePropertyGPSLatitude as String]
                    exifInfo["longitude"] = gps[kCGImagePropertyGPSLongitude as String]
                    exifInfo["altitude"] = gps[kCGImagePropertyGPSAltitude as String]
                }
                
                // 图片基本信息
                exifInfo["pixelWidth"] = imageProperties[kCGImagePropertyPixelWidth as String]
                exifInfo["pixelHeight"] = imageProperties[kCGImagePropertyPixelHeight as String]
                exifInfo["dpi"] = imageProperties[kCGImagePropertyDPIHeight as String]
                exifInfo["colorModel"] = imageProperties[kCGImagePropertyColorModel as String]
                exifInfo["profileName"] = imageProperties[kCGImagePropertyProfileName as String]
            }
            
            completion(exifInfo)
        }
}

// 计算选择的图片大小
extension ClassifyPhotoPlugin {
    
    private func calculatePhotosSize(assetIds: [String], completion: @escaping FlutterResult) {
        let assets = PHAsset.fetchAssets(withLocalIdentifiers: assetIds, options: nil)
        var phAssets: [PHAsset] = []
        var sizes: Int64 = 0 // 用于存储文件大小
        
        assets.enumerateObjects { (phAsset, _, _) in
            phAssets.append(phAsset)
            
            // 获取 PHAsset 的资源
            let resources = PHAssetResource.assetResources(for: phAsset)
            if let resource = resources.first {
                // 获取文件大小
                if let unsignedInt64 = resource.value(forKey: "fileSize") as? CLong {
                    sizes += Int64(unsignedInt64)
                }
            }
        }
        
        // 返回文件大小到 Flutter
        completion(sizes)
    }
}


class SubscriptionHandler: NSObject {
    
    @available(iOS 15.0.0, *)
    func checkTrialEligibility() async -> Bool {
        do {
            // 获取产品信息
            let productIds = ["clean.vip.1week"]
            let products = try await Product.products(for: Set(productIds))
            
            // 检查第一个产品的试用资格
            if let product = products.first {
                return await product.subscription?.isEligibleForIntroOffer ?? false
            }
            return false
        } catch {
            print("Error checking trial eligibility: \(error)")
            return false
        }
    }
}
