import Flutter
import UIKit

final class PlatformInfoPlugin: NSObject, FlutterPlugin {
  static func register(with registrar: FlutterPluginRegistrar) {
    let channel = FlutterMethodChannel(
      name: "app.record_tool/platform_info",
      binaryMessenger: registrar.messenger()
    )
    let plugin = PlatformInfoPlugin()
    registrar.addMethodCallDelegate(plugin, channel: channel)
  }

  func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
    switch call.method {
    case "packageInfo":
      result(packageInfoMap())
    case "deviceInfo":
      result(deviceInfoMap())
    case "deviceHealth":
      result(deviceHealthMap())
    default:
      result(FlutterMethodNotImplemented)
    }
  }

  private func packageInfoMap() -> [String: String] {
    let bundle = Bundle.main
    return [
      "appName": displayName(bundle: bundle),
      "packageName": bundle.bundleIdentifier ?? "",
      "version": bundle.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "",
      "buildNumber": bundle.object(forInfoDictionaryKey: "CFBundleVersion") as? String ?? "",
    ]
  }

  private func deviceHealthMap() -> [String: Any?] {
    let device = UIDevice.current
    device.isBatteryMonitoringEnabled = true

    var batteryLevelPercent: Int?
    let batteryLevel = device.batteryLevel
    if batteryLevel >= 0 {
      batteryLevelPercent = Int((batteryLevel * 100).rounded())
    }

    var storageAvailablePercent = 100.0
    if let attrs = try? FileManager.default.attributesOfFileSystem(forPath: NSHomeDirectory()),
       let free = attrs[.systemFreeSize] as? NSNumber,
       let total = attrs[.systemSize] as? NSNumber,
       total.doubleValue > 0 {
      storageAvailablePercent = free.doubleValue / total.doubleValue * 100.0
    }

    return [
      "batteryLevelPercent": batteryLevelPercent,
      "storageAvailablePercent": storageAvailablePercent,
    ]
  }

  private func deviceInfoMap() -> [String: Any] {
    let device = UIDevice.current
    return [
      "platform": "ios",
      "deviceCode": "",
      "brand": device.systemName,
      "model": machineIdentifier(),
      "systemVersion": device.systemVersion,
      "isPhysicalDevice": !isSimulator(),
    ]
  }

  private func displayName(bundle: Bundle) -> String {
    if let displayName = bundle.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String {
      return displayName
    }
    return bundle.object(forInfoDictionaryKey: "CFBundleName") as? String ?? ""
  }

  private func isSimulator() -> Bool {
    #if targetEnvironment(simulator)
      return true
    #else
      return false
    #endif
  }

  private func machineIdentifier() -> String {
    var systemInfo = utsname()
    uname(&systemInfo)
    let mirror = Mirror(reflecting: systemInfo.machine)
    let identifier = mirror.children.reduce(into: "") { value, element in
      guard let byte = element.value as? Int8, byte != 0 else { return }
      value.append(String(UnicodeScalar(UInt8(byte))))
    }
    return identifier
  }
}
