// Sources/Core/Push/NotificationDelegate.swift
// T-2.9: APNs — foreground presentation control + tap handling

import UserNotifications
import UIKit

/// Centralised `UNUserNotificationCenterDelegate`.
///
/// Responsibilities:
///  - Suppresses the banner when the user is already viewing the relevant
///    terminal session (`visibleSessionId`).
///  - Posts `"piRemote.openSession"` when the user taps a notification,
///    carrying the session-id as the notification object, so any subscriber
///    (e.g. the root navigation stack) can navigate to the right session.
@MainActor
final class NotificationDelegate: NSObject, UNUserNotificationCenterDelegate, ObservableObject {

    // MARK: - Singleton

    static let shared = NotificationDelegate()

    private override init() {}

    // MARK: - State

    /// Set by the visible terminal view so foreground banners can be suppressed.
    var visibleSessionId: String? = nil

    // MARK: - Setup

    /// Wire this delegate into `UNUserNotificationCenter`.
    /// Call once from `piRemoteApp.onAppear`.
    func setup() {
        UNUserNotificationCenter.current().delegate = self
    }

    // MARK: - Permission

    /// Request alert + sound + badge authorisation.
    /// - Returns: `true` if the user granted permission.
    func requestPermission() async -> Bool {
        do {
            return try await UNUserNotificationCenter.current()
                .requestAuthorization(options: [.alert, .sound, .badge])
        } catch {
            return false
        }
    }

    // MARK: - UNUserNotificationCenterDelegate

    /// Foreground presentation: suppress the banner when the relevant session
    /// is already on-screen.
    nonisolated func userNotificationCenter(
        _ center: UNUserNotificationCenter,
        willPresent notification: UNNotification,
        withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
    ) {
        let sessionId = notification.request.content.userInfo["sessionId"] as? String

        nonisolated(unsafe) let ch = completionHandler
        Task { @MainActor in
            if let sessionId, sessionId == self.visibleSessionId {
                ch([])
            } else {
                ch([.banner, .sound, .badge])
            }
        }
    }

    /// Tap handling: post `"piRemote.openSession"` so any subscriber can
    /// navigate to the correct session without a tight coupling.
    nonisolated func userNotificationCenter(
        _ center: UNUserNotificationCenter,
        didReceive response: UNNotificationResponse,
        withCompletionHandler completionHandler: @escaping () -> Void
    ) {
        let sessionId = response.notification.request.content.userInfo["sessionId"] as? String

        nonisolated(unsafe) let ch = completionHandler
        Task { @MainActor in
            NotificationCenter.default.post(
                name: Notification.Name("piRemote.openSession"),
                object: sessionId
            )
            ch()
        }
    }
}
