//
//  AppDelegate.swift
//  SodaLive
//
//  Created by klaus on 2023/08/09.
//

import UIKit

import AppsFlyerLib
import FBSDKCoreKit
import FirebaseCore
import FirebaseAnalytics
import FirebaseMessaging

class AppDelegate: UIResponder, UIApplicationDelegate {
    
    private let gcmMessageIDKey = "gcm.message_id"
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        FirebaseApp.configure()
        Messaging.messaging().delegate = self
        
        // For iOS 10 display notification (sent via APNS)
        UNUserNotificationCenter.current().delegate = self
        
        let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
        UNUserNotificationCenter.current().requestAuthorization(
            options: authOptions,
            completionHandler: {_, _ in })
        
        application.registerForRemoteNotifications()
        UIApplication.shared.applicationIconBadgeNumber = 0
        
        ApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)
        AppEvents.shared.activateApp()
        
        setupAppsFlyer()
        
        return true
    }
    
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        Messaging.messaging().appDidReceiveMessage(userInfo)
        // Print message ID.
        if let messageID = userInfo[gcmMessageIDKey] {
            DEBUG_LOG("Message ID: \(messageID)")
        }
        
        // Print full message.
        DEBUG_LOG("userInfo: \(userInfo)")
        
        completionHandler(UIBackgroundFetchResult.newData)
    }
    
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        UserDefaults.set(deviceToken, forKey: .devicePushToken)
        Messaging.messaging().apnsToken = deviceToken
    }
    
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
    }
    
    func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([any UIUserActivityRestoring]?) -> Void) -> Bool {
        AppsFlyerLib.shared().continue(userActivity, restorationHandler: nil)
        return true
    }
    
    private func setupAppsFlyer() {
        if let infoDic = Bundle.main.infoDictionary, let devKey = infoDic["AppsFlyerDevKey"] as? String, let appId = infoDic["AppsFlyerAppID"] as? String {
            AppsFlyerLib.shared().appsFlyerDevKey = devKey
            AppsFlyerLib.shared().appleAppID = appId
        } else {
            AppsFlyerLib.shared().appsFlyerDevKey = "tWF2wbJ5nSkya5Ru9mGcPU"
            AppsFlyerLib.shared().appleAppID = "6461721697"
        }
        
        AppsFlyerLib.shared().waitForATTUserAuthorization(timeoutInterval: 60)
        
        AppsFlyerLib.shared().delegate = self
        AppsFlyerLib.shared().deepLinkDelegate = self
    }
    
    private func logUtmInFirebase() {
        FirebaseTracking.shared.logUtm()
    }
}

extension AppDelegate: AppsFlyerLibDelegate {
    func onConversionDataSuccess(_ conversionInfo: [AnyHashable : Any]) {
        DEBUG_LOG("AppsFlyer Conversion Data: \(conversionInfo)")
    }
    
    func onConversionDataFail(_ error: any Error) {
        DEBUG_LOG("AppsFlyer Conversion Data Failed: \(error.localizedDescription)")
    }
}

extension AppDelegate: DeepLinkDelegate {
    func didResolveDeepLink(_ result: DeepLinkResult) {
        switch result.status {
        case .notFound:
            DEBUG_LOG("[AFSDK] Deep link not found")
            return
        case .failure:
            DEBUG_LOG("Error \(result.error!)")
            return
        case .found:
            DEBUG_LOG("[AFSDK] Deep link found")
        }
        
        guard let deepLinkObj:DeepLink = result.deepLink else {
            DEBUG_LOG("[AFSDK] Could not extract deep link object")
            return
        }
        
        let pid = deepLinkObj.clickEvent["deep_link_sub1"] as? String ?? ""
        if !pid.isEmpty {
            UserDefaults.set(pid, forKey: .marketingPid)
        }
        
        AppState.shared.marketingUtmSource = deepLinkObj.clickEvent["deep_link_sub2"] as? String ?? ""
        AppState.shared.marketingUtmMedium = deepLinkObj.clickEvent["deep_link_sub3"] as? String ?? ""
        AppState.shared.marketingUtmCampaign = deepLinkObj.clickEvent["deep_link_sub4"] as? String ?? ""
        
        let deepLinkValue = deepLinkObj.clickEvent["deep_link_value"] as? String ?? ""
        let deepLinkValueId = Int(deepLinkObj.clickEvent["deep_link_sub5"] as? String ?? "") ?? 0
        
        if deepLinkValueId > 0 {
            if deepLinkValue == "series" {
                AppState.shared.pushSeriesId = deepLinkValueId
            } else if deepLinkValue == "content" {
                AppState.shared.pushAudioContentId = deepLinkValueId
            } else if deepLinkValue == "live" {
                AppState.shared.pushRoomId = deepLinkValueId
            } else if deepLinkValue == "channel" {
                AppState.shared.pushChannelId = deepLinkValueId
            }
        }
        
        logUtmInFirebase()
    }
}

extension AppDelegate: MessagingDelegate {
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
        if let fcmToken = fcmToken {
            DEBUG_LOG("fcmToken: \(fcmToken)")
            UserDefaults.set(fcmToken, forKey: .pushToken)
        }
    }
}

extension AppDelegate : UNUserNotificationCenterDelegate {
    
    // Receive displayed notifications for iOS 10 devices.
    func userNotificationCenter(
        _ center: UNUserNotificationCenter,
        willPresent notification: UNNotification,
        withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
    ) {
        let userInfo = notification.request.content.userInfo
        
        // With swizzling disabled you must let Messaging know about the message, for Analytics
        Messaging.messaging().appDidReceiveMessage(userInfo)
        
        // ...
        
        // Print full message.
        DEBUG_LOG("userInfo: \(userInfo)")
        
        // Change this to your preferred presentation option
        completionHandler([.banner, .badge, .sound])
    }
    
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Void) {
        let userInfo = response.notification.request.content.userInfo
        
        // With swizzling disabled you must let Messaging know about the message, for Analytics
        Messaging.messaging().appDidReceiveMessage(userInfo)
        
        let roomIdString = userInfo["room_id"] as? String
        let contentIdString = userInfo["content_id"] as? String
        let channelIdString = userInfo["channel_id"] as? String
        let messageIdString = userInfo["message_id"] as? String
        let auditionIdString = userInfo["audition_id"] as? String
        
        if let roomIdString = roomIdString, let roomId = Int(roomIdString), roomId > 0 {
            AppState.shared.pushRoomId = roomId
        }
        
        if let contentIdString = contentIdString, let audioContentId = Int(contentIdString), audioContentId > 0 {
            AppState.shared.pushAudioContentId = audioContentId
        }
        
        if let channelIdString = channelIdString, let channelId = Int(channelIdString), channelId > 0 {
            AppState.shared.pushChannelId = channelId
        }
        
        if let messageIdString = messageIdString, let messageId = Int(messageIdString), messageId > 0 {
            AppState.shared.pushMessageId = messageId
        }
        
        if let auditionIdString = auditionIdString, let auditionId = Int(auditionIdString), auditionId > 0 {
            AppState.shared.startTab = .audition
            NotificationCenter.default.post(name: .didReceiveHomeTab, object: HomeViewModel.CurrentTab.audition)
        }
        
        completionHandler()
    }
}

extension Notification.Name {
    static let didReceiveHomeTab = Notification.Name("didReceiveHomeTab")
}