//
//  DeviceInfoInteractor.swift
//  AirbridgeQA
//
//  Created by WOF on 6/24/24.
//

import React
import CoreTelephony
import SystemConfiguration

@objc(DeviceInfoInteractor)
class DeviceInfoInteractor: NSObject {
  @objc(deviceInfo:reject:)
  func deviceInfo(
    resolve: @escaping RCTPromiseResolveBlock,
    reject: @escaping RCTPromiseRejectBlock
  ) {
    let response: [AnyHashable: Any] = [
      "responseCode": 200,
      "data": fetch()
    ]
    resolve(String(
      data: try! JSONSerialization.data(withJSONObject: response),
      encoding: .utf8
    ))
  }
  
  func fetch() -> [String: Any?] {
    return [
      "deviceModel": UIDevice.current.localizedModel,
      "deviceManufacturer": "Apple",
      "osVersion": UIDevice.current.systemVersion,
      "locale": getSystemLocale(),
      "timezone": TimeZone.current.description,
      "orientation": {
        if UIDevice.current.orientation.isLandscape {
            return "landscape"
        } else {
            return "portrait"
        }
      }(),
      "screenSize": "\(width)x\(height) \(density)DPI",
      "networkCarrier": {
        let info = CTTelephonyNetworkInfo()

        if #available(iOS 12.1, *) {
            let providers = info.serviceSubscriberCellularProviders
            return providers?.values.first?.carrierName
        } else {
            let provider = info.subscriberCellularProvider
            return provider?.carrierName
        }
      }(),
      "cellularStatus": isCellular(),
      "wifiStatus": isWifi(),
    ]
  }
}

extension DeviceInfoInteractor {
  func getSystemLocale() -> String? {
      guard let language = getSystemLanguage() else { return nil }
      guard let country = getSystemCountry() else { return nil }
      
      return "\(language)-\(country)"
  }

  func getSystemLanguage() -> String? {
      let languages = Locale.preferredLanguages
      
      if languages.count < 1 {
          return nil
      }
      
      let languageSource = languages[0]
      
      guard let barIndex = languageSource.range(of: "-") else {
          return languageSource
      }
      
      return String(languageSource[..<barIndex.lowerBound])
  }

  func getSystemCountry() -> String? {
      return Locale.autoupdatingCurrent.regionCode
  }
}

extension DeviceInfoInteractor {
  var width: String {
    String(format: "%.f", UIScreen.main.bounds.size.width)
  }
  
  var height: String {
    String(format: "%.f", UIScreen.main.bounds.size.width)
  }
  
  var density: String {
    String(format: "%.f", UIScreen.main.bounds.size.width)
  }
}

extension DeviceInfoInteractor {
  func isCellular() -> Bool {
      return getNetworkInfo() == .cellular
  }
  
  func isWifi() -> Bool {
      return getNetworkInfo() == .wifi
  }

  enum Network {
      case wifi
      case cellular
      case none
  }

  func getNetworkInfo() -> Network {
      var zeroAddress = sockaddr()
      bzero(&zeroAddress, MemoryLayout.size(ofValue: zeroAddress))
      zeroAddress.sa_len = __uint8_t(MemoryLayout.size(ofValue: zeroAddress))
      zeroAddress.sa_family = sa_family_t(AF_INET)

      guard let reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, &zeroAddress) else {
          return .none
      }

      var flags = SCNetworkReachabilityFlags()
      if !SCNetworkReachabilityGetFlags(reachability, &flags) {
          return .none
      }

      if !flags.contains(.reachable) {
          return .none
      }

      if flags.contains(.connectionRequired)
          && !((flags.contains(.connectionOnDemand) || flags.contains(.connectionOnTraffic))
              && !flags.contains(.interventionRequired)) {
          return .none
      }
      
      if flags.contains(.isWWAN) {
          return .cellular
      } else {
          return .wifi
      }
  }
}
