import Flutter
import UIKit
import UserNotifications

// Mirrors LockInBroMobile/Services/NotificationService.swift: pure native APNs,
// no Firebase. The hex device token is forwarded to Dart over a MethodChannel
// (`blindmaster/apns`) which then POSTs it to /register_apns_token.
@main
@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate, UNUserNotificationCenterDelegate {
  private var apnsChannel: FlutterMethodChannel?
  private var pendingToken: String?

  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    UNUserNotificationCenter.current().delegate = self
    // Trigger APNs registration on every launch so iOS calls
    // didRegisterForRemoteNotificationsWithDeviceToken with a fresh token.
    application.registerForRemoteNotifications()
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

  func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
    GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)

    let registrar = engineBridge.pluginRegistry.registrar(forPlugin: "BlindMasterApns")
    let channel = FlutterMethodChannel(
      name: "blindmaster/apns",
      binaryMessenger: registrar.messenger()
    )
    channel.setMethodCallHandler { [weak self] call, result in
      switch call.method {
      case "requestPermission":
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
          if let error = error { print("[APNs] permission error: \(error)") }
          DispatchQueue.main.async {
            UIApplication.shared.registerForRemoteNotifications()
          }
          result(granted)
        }
      case "getToken":
        result(self?.pendingToken)
      default:
        result(FlutterMethodNotImplemented)
      }
    }
    apnsChannel = channel

    // If iOS already delivered the token before Dart attached the channel,
    // flush it now so the upload still happens.
    if let token = pendingToken {
      channel.invokeMethod("onToken", arguments: token)
    }
  }

  override func application(
    _ application: UIApplication,
    didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
  ) {
    let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
    pendingToken = token
    apnsChannel?.invokeMethod("onToken", arguments: token)
    super.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
  }

  override func application(
    _ application: UIApplication,
    didFailToRegisterForRemoteNotificationsWithError error: Error
  ) {
    print("[APNs] registration failed: \(error)")
    super.application(application, didFailToRegisterForRemoteNotificationsWithError: error)
  }

  // Show banners while the app is in the foreground (matches LockInBroMobile).
  override func userNotificationCenter(
    _ center: UNUserNotificationCenter,
    willPresent notification: UNNotification,
    withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
  ) {
    completionHandler([.banner, .sound, .badge])
  }
}
