//
//  AppDelegate.swift
//  JJUNGTABLE
//
//  Created by Sean Kim on 10/26/23.
//

import UIKit
import SwiftUI
import Combine

import UserNotifications

import Firebase
import FirebaseMessaging

import KakaoSDKCommon




@main
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, MessagingDelegate{
    var viewModel = ViewModel()
    
    private var cancellables = Set<AnyCancellable>()
    private var version: [Version] = []
    
    private let gcmMessageIDKey = "gcm.message_id"
    
//    private var cancellables = Set<AnyCancellable>()
//    private var versions: [Version] = []

    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }

    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
    }
    
    private func checkVersion() {
        API.shared.readData(path: "/db/version/read",
                            queryItems: [URLQueryItem(name: "os_type", value: "I")])
        .sink { completion in
            switch completion {
            case .finished:
                printLog(self.version)
                
                //현재 버전이 업데이트 버전보다 OOO 하다
                switch compareVersion(currentVersion(), self.version[0].update_ver) {
                case .bigger: 
                    self.viewModel.isUpdate = "N"
                case .smaller, .equal:
                    self.viewModel.isUpdate = "Y"
                case .error:
                    self.viewModel.alertData = self.viewModel.systemErrorAlert()
                    self.viewModel.showAlert.toggle()
                }
                
                switch compareVersion(currentVersion(), self.version[0].final_ver) {
                case .bigger, .equal:
                    //  현재 버전이 스토어 버전보다 높거나 같을 같을 떄 - 이상 x
                    break
                case .smaller:
                    let choice = self.version[0].update_choice == "Y" ? true : false
                    switch compareVersion(currentVersion(), self.version[0].force_ver) {
                    case .bigger, .equal:
                        // 현재 버전이 강업보다 높다
                        if !choice {
                            break // 업데이트를 안내할 필요 없음
                        }
                        else {
                            self.viewModel.alertData = .init(title: "업데이트 안내",
                                                        body: """
                                                          앱 최신 버전이 새로 나왔습니다.
                                                          지금 업데이트 하시겠어요?
                                                          """,
                                                        button: [ButtonType(name: "지금 업데이트", role: .cancel ,
                                                                            function: {exit(1)}),
                                                                 ButtonType(name: "나중에", role: .none ,
                                                                            function: nil),
                                                        ])
                            self.viewModel.showAlert.toggle()
                        }
                    case .smaller:
                        // 현재 버전이 강업보다 닞다 -> 강업을 해야 한다.
                        self.viewModel.alertData = .init(title: "업데이트 안내",
                                                    body: """
                                                          시스템이 제대로 동작하지 못했습니다.
                                                          앱을 종료후 다시 실행해주세요.
                                                          """,
                                                    button: [ButtonType(name: "지금 업데이트", role: .none,
                                                                        function: {exit(1)})])
                        self.viewModel.showAlert.toggle()
                    case .error:
                        self.viewModel.alertData = self.viewModel.systemErrorAlert()
                        self.viewModel.showAlert.toggle()
                    }
                case .error:
                    self.viewModel.alertData = self.viewModel.systemErrorAlert()
                    self.viewModel.showAlert.toggle()
                }
                // 버전 비교 처리
            case .failure(let error):
                printLog(error)
                self.viewModel.alertData = self.viewModel.systemErrorAlert()
                self.viewModel.showAlert.toggle()
            }
        } receiveValue: { data in
            do {
                let decoder = JSONDecoder()
                self.version = try decoder.decode([Version].self, from: data)
            } catch {
                printLog(error)
                self.viewModel.alertData = self.viewModel.systemErrorAlert()
                self.viewModel.showAlert.toggle()
            }
        }
        .store(in: &cancellables)
    }
}


// MARK: - 기초 셋업
extension AppDelegate {
    func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        printLog("Start Set AppDelegate")
        if isIllegalDevice() {
            viewModel.alertData = .init(title:"경고",
                                        body: """
                                              변경된 OS('탈옥'등)의 스마트폰은 서비스를 이용할수 없습니다.
                                              """,
                                        button: [ButtonType(name: "확인", role: .none ,
                                                            function: {exit(1)})])
            viewModel.showAlert.toggle()
        }
        else {
            checkVersion()
            
            // Firebase 설정
            FirebaseApp.configure()
            
            
            // App Check 설정
            //        AppCheck.setAppCheckProviderFactory(AppCheckDebugProviderFactory())
            
            // 카카오 SDK 초기화 코드
            KakaoSDK.initSDK(appKey: KEY.kakaoAppKey)
            
#if FCM
            // FCM 설정
            Messaging.messaging().delegate = self
#endif
            // Noti 설정
            UNUserNotificationCenter.current().delegate = self
            
            let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
            UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { granted, error in
                if let error = error {
                    printLog("Authorization error: \(error.localizedDescription)")
                }
                if granted {
                    DispatchQueue.main.async {
                        UIApplication.shared.registerForRemoteNotifications()
                    }
                } else {
                    printLog("Notification permission denied.")
                }
            }
            
            application.registerForRemoteNotifications()
            UIApplication.shared.registerForRemoteNotifications()
            
            // 네트워크 모니터 초기화
            _ = NetworkMonitor.shared
        }
        
        printLog("End Set AppDelegate")
        return true
    }
    
    
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
    }
    
    
}

extension AppDelegate {
    
    // 24.05.30 (수정완) - 앱이 원격 푸시 알림 등록을 성공적으로 마친 후 호출
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        
        // 파이어 베이스 SMS 하려고 하는 세팅
        Auth.auth().setAPNSToken(deviceToken, type: .unknown)
        
        printLog("원격 푸시 알림 등록 성공 ")
        
        let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02.2hX", $1)})
        viewModel.deviceToken = deviceTokenString
        
        // Firebase에 디바이스 토큰 등록
        Messaging.messaging().apnsToken = deviceToken
        printLog("DeviceToken: \(viewModel.deviceToken)")
    }
    
    // 24.05.30 (수정완) - 초기 FCM토큰 등록
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
        @UserDefault (key: "isRegisterToken", defaultValue: "F") var isRegisterToken
        printLog("토큰 등록 동작 시작")
        guard let fcmToken = fcmToken else { return }
        viewModel.pushFCMToken = fcmToken

        Task {
            if isRegisterToken == "F" {
//                switch await FB_CRUD.shared.create("Token", doc: "\(viewModel.deviceToken)",
//                                                   data: ["fcmToken":"\(viewModel.pushFCMToken)"]) {
//                case .success(_):
//                    viewModel.pushFCMToken = fcmToken
//                    isRegisterToken = "T"
//                    printLog("초기 토큰 등록 성공")
//                case .failure(let error):
//                    isRegisterToken = "F"
//                    viewModel.alertData = .init(body:"""
//                                                        시스템이 제대로 동작하지 못했습니다.
//                                                        앱을 종료후 다시 실행해주세요.
//                                                    """,
//                                                button: [ButtonType(name: "종료", role: .destructive ,function: {exit(1)})])
//                    viewModel.showAlert.toggle()
//                    printLog("초기 토큰 등록 실패")
//                }
            }
            else {
//                if viewModel.pushFCMToken != fcmToken {
//                    switch await FB_CRUD.shared.update("Token", doc: "\(viewModel.deviceToken)",
//                                                       data: ["fcmToken":"\(viewModel.pushFCMToken)"]) {
//                    case .success(_):
//                        viewModel.pushFCMToken = fcmToken
//                        isRegisterToken = "T"
//                        printLog("토큰 재등록 성공")
//                    case .failure(_):
//                        viewModel.alertData = .init(body:"""
//                                                            시스템이 제대로 동작하지 못했습니다.
//                                                            앱을 종료후 다시 실행해주세요.
//                                                        """,
//                                                    button: [ButtonType(name: "종료", role: .destructive ,function: {exit(1)})])
//                        viewModel.showAlert.toggle()
//                        printLog("토큰 재등록 실패")
//                    }
//                }
            }
            printLog("FCM Token: \(viewModel.pushFCMToken)")
        }
    }
    
    
    // 앱 켜져있을때 알럿 받으면
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification) async -> UNNotificationPresentationOptions {
        
        let userInfo = notification.request.content.userInfo
        
        //파이어 베이스 SMS 수신설정 부
        if Auth.auth().canHandleNotification(userInfo) {
            return []
        }
        
        if let apsData = userInfo["aps"] as? [AnyHashable: Any],
           let messageId = userInfo["gcm.message_id"] as? String,
           let badge = apsData["badge"] as? Int {
            
//            switch await FB_CRUD.shared.read("Users", doc: "\(viewModel.userId)") {
//            case .success(let data):
//                if var noReadList = data["noReadAlert"] as? [String] {
//                    noReadList.append(messageId)
//                    viewModel.noReadAlertList = noReadList
//                    switch await FB_CRUD.shared.update("Users", doc: "\(viewModel.userId)",
//                                                       data: ["noReadAlert":noReadList]) {
//                    case .success(let data):
//                        await viewModel.setBadge()
//                    case .failure(let gg):
//                        printLog(noReadList)
//                    }
//                    printLog(viewModel.noReadAlertList)
//                    printLog(viewModel.noReadAlertList.count)
//                    
//                }
//            case .failure(let failure):
//                printLog(failure)
//            }
            
        }
        
        Messaging.messaging().appDidReceiveMessage(userInfo)
        
        
        
        
        if #available(iOS 14.0, *) {
            return [[.list,.banner,.sound]]
        } else {
            return[[.alert,.sound]]
        }
        
        
        
    }
    
    // Background 상태에서 수신 받은 Notification을 터치해 앱으로 진입했을 때 호출
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse)  {
        printLog("ININININININi")
        let userInfo = response.notification.request.content.userInfo
        
        //파이어 베이스 SMS 수신설정 부
        if Auth.auth().canHandleNotification(userInfo) {
            return
        }
        
        if let apsData = userInfo["aps"] as? [AnyHashable: Any] {
            if let alert = apsData["alert"] as? [AnyHashable: Any],
               let messageKey = apsData[gcmMessageIDKey] as? String {
                printLog("apsData: \(apsData)")
                printLog("alert: \(alert)")
                printLog("key: \(messageKey)")
                if let param = alert["parameter"] {
                    printLog(param as? String)
                }
//                viewModel.setBadge()
            }
        }
    }
    
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        
        // 파이어 베이스 SMS 설정부
        if Auth.auth().canHandleNotification(userInfo) {
            completionHandler(.noData)
            return
        }
        
//        printLog("Back = \(userInfo)")
//        FB_CRUD.shared.sendPushNotification("확인", body: "확인")
//        @UserDefault (key: "fcmToken", defaultValue: "") var pushFCMToken
//        @UserDefault (key: "userId", defaultValue: "") var userId
//        @UserDefault (key: "noReadAlertList", defaultValue: [""]) var noReadAlertList
//
//        let userInfo = notification.request.content.userInfo
//
//        if let apsData = userInfo["aps"] as? [AnyHashable: Any],
//           let messageId = userInfo["gcm.message_id"] as? String,
//           let badge = apsData["badge"] as? Int {
//
//            switch await FB_CRUD.shared.read("Users", doc: "\(userId)") {
//            case .success(let data):
//                printLog(data)
//                if var noReadList = data["noReadAlert"] as? [String] {
//                    noReadList.append(messageId)
//                    noReadAlertList = noReadList
//                    await FB_CRUD.shared.update("Users", doc: "\(userId)",
//                                                data: ["noReadAlert":noReadList])
//                    printLog(noReadList)
//                    printLog(noReadAlertList)
//                    printLog(noReadAlertList.count)
//                    await viewModel.setBadge(badge: noReadAlertList.count)
//                }
//            case .failure(let failure):
//                printLog(failure)
//            }
//
//        }
    }
    

}



