import Flutter
import UIKit
import UserNotifications

final class QlyraNotifications: NSObject {
  static let shared = QlyraNotifications()

  private static let chatKeys = ["qlyra_chat", "chatId", "chat_id"]

  private var sink: FlutterEventSink?
  private var pendingChatId: Int64 = 0
  private var activeChatId: Int64 = 0

  func start() {
    UNUserNotificationCenter.current().delegate = self
  }

  func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
    switch call.method {
    case "consumeInitialChat":
      let chatId = pendingChatId
      pendingChatId = 0
      result(chatId > 0 ? NSNumber(value: chatId) : nil)
    case "setActiveChat":
      activeChatId = Self.chatId(from: call.arguments)
      dismissDelivered(chatId: activeChatId)
      result(nil)
    case "clearActiveChat":
      activeChatId = 0
      result(nil)
    default:
      result(FlutterMethodNotImplemented)
    }
  }

  func attach(_ sink: FlutterEventSink?) {
    self.sink = sink
  }

  func deliver(chatId: Int64) {
    guard chatId > 0 else { return }
    if let sink = sink {
      sink(NSNumber(value: chatId))
    } else {
      pendingChatId = chatId
    }
  }

  private func dismissDelivered(chatId: Int64) {
    guard chatId > 0 else { return }
    let center = UNUserNotificationCenter.current()
    center.getDeliveredNotifications { delivered in
      let identifiers = delivered
        .filter { Self.chatId(from: $0.request.content.userInfo) == chatId }
        .map { $0.request.identifier }
      guard !identifiers.isEmpty else { return }
      center.removeDeliveredNotifications(withIdentifiers: identifiers)
    }
  }

  private static func chatId(from raw: Any?) -> Int64 {
    if let number = raw as? NSNumber { return number.int64Value }
    if let text = raw as? String { return Int64(text) ?? 0 }
    if let map = raw as? [AnyHashable: Any] {
      for key in chatKeys {
        if let value = map[key], let parsed = optionalChatId(value) { return parsed }
      }
    }
    return 0
  }

  private static func optionalChatId(_ raw: Any) -> Int64? {
    if let number = raw as? NSNumber { return number.int64Value }
    if let text = raw as? String { return Int64(text) }
    return nil
  }
}

extension QlyraNotifications: UNUserNotificationCenterDelegate {
  func userNotificationCenter(
    _ center: UNUserNotificationCenter,
    willPresent notification: UNNotification,
    withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
  ) {
    let chatId = Self.chatId(from: notification.request.content.userInfo)
    if chatId > 0, chatId == activeChatId {
      completionHandler([])
      return
    }
    if #available(iOS 14.0, *) {
      completionHandler([.banner, .list, .sound, .badge])
    } else {
      completionHandler([.alert, .sound, .badge])
    }
  }

  func userNotificationCenter(
    _ center: UNUserNotificationCenter,
    didReceive response: UNNotificationResponse,
    withCompletionHandler completionHandler: @escaping () -> Void
  ) {
    deliver(chatId: Self.chatId(from: response.notification.request.content.userInfo))
    completionHandler()
  }
}
