import Foundation
import UIKit
import React

@objc(DeviceIdModule)
class DeviceIdModule: NSObject {
  
  @objc
  static func requiresMainQueueSetup() -> Bool {
    return false
  }
  
  @objc
  func getDeviceId(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) -> Void {
    DispatchQueue.main.async {
      do {
        let deviceId = self.getUniqueDeviceId()
        resolve(deviceId)
      } catch {
        reject("DEVICE_ID_ERROR", "Failed to get device ID", error)
      }
    }
  }
  
  @objc
  func getDeviceInfo(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) -> Void {
    DispatchQueue.main.async {
      do {
        let deviceInfo = self.collectDeviceInfo()
        resolve(deviceInfo)
      } catch {
        reject("DEVICE_INFO_ERROR", "Failed to get device info", error)
      }
    }
  }
  
  private func getUniqueDeviceId() -> String {
    // Use identifierForVendor for a unique identifier per app installation
    // This changes when all apps from the vendor are uninstalled
    if let identifierForVendor = UIDevice.current.identifierForVendor?.uuidString {
      print("📱 iOS DeviceId: Generated identifierForVendor:", identifierForVendor)
      return identifierForVendor
    }
    
    // Fallback to a combination of device characteristics
    let fallbackId = generateFallbackId()
    print("📱 iOS DeviceId: Using fallback ID:", fallbackId)
    return fallbackId
  }
  
  private func generateFallbackId() -> String {
    // Create a fallback ID using device characteristics
    let device = UIDevice.current
    let systemName = device.systemName
    let systemVersion = device.systemVersion
    let model = device.model
    let name = device.name
    
    // Create a hash from device characteristics
    let combinedString = "\(systemName)-\(systemVersion)-\(model)-\(name)"
    let hash = combinedString.hash
    
    return "ios-fallback-\(abs(hash))"
  }
  
  private func collectDeviceInfo() -> [String: Any] {
    let device = UIDevice.current
    
    var deviceInfo: [String: Any] = [:]
    
    // Basic device information
    deviceInfo["systemName"] = device.systemName
    deviceInfo["systemVersion"] = device.systemVersion
    deviceInfo["model"] = device.model
    deviceInfo["name"] = device.name
    deviceInfo["localizedModel"] = device.localizedModel
    
    // Enhanced device identification
    deviceInfo["deviceType"] = getDeviceType()
    deviceInfo["deviceGeneration"] = getDeviceGeneration()
    
    // Device capabilities
    deviceInfo["isMultitaskingSupported"] = device.isMultitaskingSupported
    deviceInfo["userInterfaceIdiom"] = device.userInterfaceIdiom.rawValue
    
    // Identifier for vendor (if available)
    if let identifierForVendor = device.identifierForVendor?.uuidString {
      deviceInfo["identifierForVendor"] = identifierForVendor
    }
    
    // Screen information
    let screen = UIScreen.main
    deviceInfo["screenBounds"] = [
      "width": screen.bounds.width,
      "height": screen.bounds.height
    ]
    deviceInfo["screenScale"] = screen.scale
    deviceInfo["screenNativeBounds"] = [
      "width": screen.nativeBounds.width,
      "height": screen.nativeBounds.height
    ]
    
    // Battery information
    device.isBatteryMonitoringEnabled = true
    deviceInfo["batteryLevel"] = device.batteryLevel
    deviceInfo["batteryState"] = device.batteryState.rawValue
    
    // Additional system information
    deviceInfo["isSimulator"] = isSimulator()
    deviceInfo["architecture"] = getArchitecture()
    
    print("📱 iOS DeviceId: Collected enhanced device info:", deviceInfo)
    
    return deviceInfo
  }
  
  private func getDeviceType() -> String {
    let device = UIDevice.current
    switch device.userInterfaceIdiom {
    case .phone:
      return "iPhone"
    case .pad:
      return "iPad"
    case .tv:
      return "Apple TV"
    case .carPlay:
      return "CarPlay"
    case .mac:
      return "Mac"
    case .vision:
      return "Vision Pro"
    @unknown default:
      return "Unknown"
    }
  }
  
  private func getDeviceGeneration() -> String {
    let device = UIDevice.current
    let model = device.model
    
    // Try to get more specific device info
    var systemInfo = utsname()
    uname(&systemInfo)
    let modelCode = String(bytes: Data(bytes: &systemInfo.machine, count: Int(_SYS_NAMELEN)), encoding: .ascii)?.trimmingCharacters(in: .controlCharacters) ?? "Unknown"
    
    return modelCode
  }
  
  private func isSimulator() -> Bool {
    #if targetEnvironment(simulator)
    return true
    #else
    return false
    #endif
  }
  
  private func getArchitecture() -> String {
    #if arch(arm64)
    return "arm64"
    #elseif arch(arm)
    return "arm"
    #elseif arch(x86_64)
    return "x86_64"
    #elseif arch(i386)
    return "i386"
    #else
    return "unknown"
    #endif
  }
}
