//
//  AppDelegate.swift
//  MyHybridStarter
//
//  Created by Terrence Mahachi on 2025/10/24.
//  © 2025 Gramia Technologies. All rights reserved.
//

import UIKit
import UserNotifications
import BackgroundTasks

var sharedAppDelegate: AppDelegate?
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
    static let notificationOpenedName = Notification.Name("GramiaNotificationOpened")
    static var pendingNotificationOpen: [String: Any]?

    // MARK: - UIApplicationDelegate lifecycle
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        sharedAppDelegate = self
        if let remoteNotification = launchOptions?[.remoteNotification] as? [AnyHashable: Any] {
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) {
                self.emitNotificationOpened(userInfo: remoteNotification)
            }
        }
        // 🔔 Request permission for notifications
        let center = UNUserNotificationCenter.current()
        center.delegate = self
        center.requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
            if let error = error {
                print("❌ Notification permission error:", error.localizedDescription)
            } else {
                print("🔔 Notification permission granted:", granted)
                if granted {
                    DispatchQueue.main.async {
                        UIApplication.shared.registerForRemoteNotifications()
           //             print("📡 registerForRemoteNotifications() called")
                    }
                    DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
                        UIApplication.shared.registerForRemoteNotifications()
           //             print("📡 Retrying APNs registration after delay")
                    }
                }
            }
        }
        
        // 🕒 Register background task
        BGTaskScheduler.shared.register(
            forTaskWithIdentifier: "com.gramiatechnologies.gramia.notificationFetch",
            using: nil
        ) { task in
            self.handleNotificationFetch(task: task as! BGAppRefreshTask)
        }

        NotificationCenter.default.addObserver(
            self,
            selector: #selector(handleKeyboardDidShow),
            name: UIResponder.keyboardDidShowNotification,
            object: nil
        )
        
        print("✅ AppDelegate didFinishLaunchingWithOptions complete")
        return true
    }
    
    // MARK: - Remote Notification Token Handling
    // MARK: - APNs Registration Handlers
    
    func application(_ application: UIApplication,
                     didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }
        let token = tokenParts.joined()
      //  print("📱 Device registered with APNs token:", token)
        
        // ✅ Only save temporarily
        UserDefaults.standard.set(token, forKey: "pending_apns_token")
        
        // Check if we already have user details
        if let userId = UserDefaults.standard.string(forKey: "user_id"),
           let institutionUserId = UserDefaults.standard.string(forKey: "institution_user_id") {
            print("📲 Registering new token for user \(userId) / institution_user \(institutionUserId)")
            registerDeviceTokenToServer(token) { success in
                if success {
                    // ✅ Only persist token after successful server registration
                    UserDefaults.standard.set(token, forKey: "apns_token")
                    UserDefaults.standard.removeObject(forKey: "pending_apns_token")
             //       print("✅ Token registered and saved successfully.")
                } else {
                    print("⚠️ Failed to register token on server — will retry later.")
                }
            }
        } else {
            print("⚠️ Missing user IDs; skipping device registration for now.")
        }
    }
    
    func application(
        _ application: UIApplication,
        didFailToRegisterForRemoteNotificationsWithError error: Error
    ) {
        print("❌ Failed to register for APNs:", error.localizedDescription)
    }
    
    // MARK: - Notification Delegate (Foreground)
    func userNotificationCenter(
        _ center: UNUserNotificationCenter,
        willPresent notification: UNNotification,
        withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
    ) {
        completionHandler([.banner, .sound, .badge])
    }

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

    private func emitNotificationOpened(userInfo: [AnyHashable: Any]) {
        let payload: [String: Any] = [
            "notification_id": stringifyNotificationValue(userInfo["notification_id"]),
            "type": stringifyNotificationValue(userInfo["type"]),
            "item": stringifyNotificationValue(userInfo["item"]),
            "institution_user": stringifyNotificationValue(userInfo["institution_user"]),
            "open_view": stringifyNotificationValue(userInfo["open_view"]).isEmpty ? "notifications" : stringifyNotificationValue(userInfo["open_view"])
        ]
        AppDelegate.pendingNotificationOpen = payload
        NotificationCenter.default.post(
            name: AppDelegate.notificationOpenedName,
            object: nil,
            userInfo: payload
        )
    }

    private func stringifyNotificationValue(_ value: Any?) -> String {
        if let value = value as? String { return value }
        if let value = value as? NSNumber { return value.stringValue }
        if let value = value { return String(describing: value) }
        return ""
    }
    
    // MARK: - Background Task Handler
    func handleNotificationFetch(task: BGAppRefreshTask) {
        scheduleNextFetch()
        
        NotificationFetcher.shared.checkForNotifications {
         //   print("📬 Background notification check completed")
            task.setTaskCompleted(success: true)
        }
        
        task.expirationHandler = {
            print("⏰ Background fetch expired")
            task.setTaskCompleted(success: false)
        }
    }
    
    // MARK: - Schedule Next Background Fetch
    func scheduleNextFetch() {
        let request = BGAppRefreshTaskRequest(identifier: "com.gramiatechnologies.gramia.notificationFetch")
        request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60) // every ~15 mins
        
        do {
            try BGTaskScheduler.shared.submit(request)
         //   print("⏳ Next background fetch scheduled.")
        } catch {
            print("⚠️ Could not schedule notification fetch:", error.localizedDescription)
        }
    }
    
    func applicationDidEnterBackground(_ application: UIApplication) {
        scheduleNextFetch()
    }

    @objc private func handleKeyboardDidShow() {
#if targetEnvironment(simulator)
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
            guard let firstResponder = UIResponder.currentFirstResponder() else { return }
            let responderClassName = NSStringFromClass(type(of: firstResponder))
            guard responderClassName.contains("WKContentView") else { return }
            let assistant = firstResponder.inputAssistantItem
            if !assistant.leadingBarButtonGroups.isEmpty || !assistant.trailingBarButtonGroups.isEmpty {
                assistant.leadingBarButtonGroups = []
                assistant.trailingBarButtonGroups = []
            }
        }
#endif
    }
    
    // MARK: - Register Device Token to Server
    func registerDeviceTokenToServer(_ token: String, completion: ((Bool) -> Void)? = nil) {
        let defaults = UserDefaults.standard

        guard
            let userId = defaults.string(forKey: "user_id"),
            let institutionUserId = defaults.string(forKey: "institution_user_id")
        else {
            print("⚠️ Missing user IDs; skipping device registration.")
            completion?(false)
            return
        }

        // 🧠 Check last registration timestamp and token
        let lastToken = defaults.string(forKey: "last_device_token")
        let lastRegistered = defaults.object(forKey: "last_token_registration_date") as? Date ?? .distantPast
        let hoursSinceLast = Date().timeIntervalSince(lastRegistered) / 3600.0

        if lastToken == token && hoursSinceLast < 24 {
            print("✅ Device already registered recently (\(Int(hoursSinceLast))h ago). Skipping.")
            completion?(true)
            return
        }

        // 🧭 Base URL
        var baseURL = NotificationFetcher.shared.apiBase
        if baseURL.isEmpty {
            baseURL = "https://www.gramia.tech/public"
        }
        baseURL = baseURL.trimmingCharacters(in: CharacterSet(charactersIn: "/"))

        let endpoint = "\(baseURL)/register-device"
        guard let url = URL(string: endpoint) else {
            print("❌ Invalid registration URL:", endpoint)
            completion?(false)
            return
        }

        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        var fields: [String: String] = [
            "user": userId,
            "institution_user": institutionUserId,
            "token": token,
            "platform": "iOS",
            "api": "true"
        ]
        if let apiToken = defaults.string(forKey: "api_token"), !apiToken.isEmpty {
            fields["api_token"] = apiToken
        }
        let body = fields
            .map { key, value in
                let escapedKey = key.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? key
                let escapedValue = value.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? value
                return "\(escapedKey)=\(escapedValue)"
            }
            .joined(separator: "&")
        request.httpBody = body.data(using: .utf8)
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")

        print("📤 Registering device token with server...")

        URLSession.shared.dataTask(with: request) { data, response, error in
            if let error = error {
                print("❌ Device registration failed:", error.localizedDescription)
                completion?(false)
                return
            }

            guard let data = data, let text = String(data: data, encoding: .utf8) else {
                print("⚠️ Empty response while registering token.")
                completion?(false)
                return
            }

            let success = text.contains("\"success\"") ||
                          text.contains("\"status\":1") ||
                          text.contains("Device registered")

            if success {
                defaults.set(token, forKey: "last_device_token")
                defaults.set(Date(), forKey: "last_token_registration_date")
                print("✅ Device token registered successfully and saved at \(Date()).")
            } else {
                print("⚠️ Registration response not successful: \(text)")
            }

            completion?(success)
        }.resume()
    }
}

private extension UIResponder {
    private static weak var _currentFirstResponder: UIResponder?

    static func currentFirstResponder() -> UIResponder? {
        _currentFirstResponder = nil
        UIApplication.shared.sendAction(
            #selector(_captureFirstResponder(_:)),
            to: nil,
            from: nil,
            for: nil
        )
        return _currentFirstResponder
    }

    @objc func _captureFirstResponder(_ sender: Any) {
        UIResponder._currentFirstResponder = self
    }
}
