//
//  SceneDelegate.swift
//  Emoney Info
//
//  Created by Wira Irawan on 22/07/24.
//

import UIKit
import AppTrackingTransparency
import GoogleMobileAds

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?
    private var hasRequestedTrackingAuthorization = false
    private var isTrackingAuthorizationRequestInFlight = false
    private var pendingTrackingCompletions: [() -> Void] = []
    private var hasStartedAdMob = false
    private weak var homeVC: HomeViewController?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = (scene as? UIWindowScene) else { return }

        let tabBar = MainTabBarController()
        tabBar.viewControllers = [
            makeHomeVC(tabBar: tabBar),
            makeSettingsVC()
        ]

        let window = UIWindow(windowScene: windowScene)
        window.rootViewController = tabBar
        window.makeKeyAndVisible()
        self.window = window
    }

    func sceneDidDisconnect(_ scene: UIScene) {
        // Called as the scene is being released by the system.
        // This occurs shortly after the scene enters the background, or when its session is discarded.
        // Release any resources associated with this scene that can be re-created the next time the scene connects.
        // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
    }

    func sceneDidBecomeActive(_ scene: UIScene) {
        // Called when the scene has moved from an inactive state to an active state.
        // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
        requestTrackingAuthorizationIfNeeded()
    }

    func sceneWillResignActive(_ scene: UIScene) {
        // Called when the scene will move from an active state to an inactive state.
        // This may occur due to temporary interruptions (ex. an incoming phone call).
    }

    func sceneWillEnterForeground(_ scene: UIScene) {
        // Called as the scene transitions from the background to the foreground.
        // Use this method to undo the changes made on entering the background.
    }

    func sceneDidEnterBackground(_ scene: UIScene) {
        // Called as the scene transitions from the foreground to the background.
        // Use this method to save data, release shared resources, and store enough scene-specific state information
        // to restore the scene back to its current state.
    }

    // MARK: - VC Factories

    private func makeHomeVC(tabBar: MainTabBarController) -> HomeViewController {
        let vc = HomeViewController()
        homeVC = vc

        vc.onScanTapped = { [weak vc] in
            guard let vc, let callback = vc as? ApduCallback else { return }
            self.startNfcScan(callback: callback)
        }

        vc.onViewHistoryTapped = { [weak vc] in
            let historyVC = HistoryHostingController()
            historyVC.riwayatList  = vc?.latestRiwayatList ?? []
            historyVC.cardLabel    = vc?.cardTypeText ?? ""
            historyVC.balanceText  = vc?.balanceText  ?? ""
            historyVC.cardNumber   = vc?.latestCardNumber ?? ""
            historyVC.modalPresentationStyle = .fullScreen
            vc?.present(historyVC, animated: true)
        }

        vc.onSettingsTapped = { [weak tabBar] in
            tabBar?.selectedIndex = 1
        }

        return vc
    }

    private func makeSettingsVC() -> UINavigationController {
        let vc = SettingsViewController()

        vc.onShowCardNumberChanged = { isOn in
            UserDefaults.standard.set(isOn, forKey: "masked")
            NotificationCenter.default.post(name: Notification.Name("refreshScreen"), object: nil)
        }

        vc.onHelpCenterTapped = { [weak vc] in
            let faqVC = FAQViewController()
            vc?.navigationController?.pushViewController(faqVC, animated: true)
        }

        vc.onAboutTapped = { [weak vc] in
            let aboutVC = AboutViewController()
            vc?.navigationController?.pushViewController(aboutVC, animated: true)
        }

        let nav = UINavigationController(rootViewController: vc)
        nav.setNavigationBarHidden(true, animated: false)
        return nav
    }

    private func requestTrackingAuthorizationIfNeeded(completion: (() -> Void)? = nil) {
        if let completion {
            pendingTrackingCompletions.append(completion)
        }

        guard #available(iOS 14, *) else {
            startAdMobSDKIfNeeded()
            flushPendingTrackingCompletions(after: 0)
            return
        }

        guard ATTrackingManager.trackingAuthorizationStatus == .notDetermined else {
            // User already responded to ATT in a previous session — start AdMob immediately.
            startAdMobSDKIfNeeded()
            flushPendingTrackingCompletions(after: 0)
            return
        }

        guard !hasRequestedTrackingAuthorization else {
            flushPendingTrackingCompletions(after: 0)
            return
        }

        hasRequestedTrackingAuthorization = true
        isTrackingAuthorizationRequestInFlight = true
        // Short delay so the root view controller completes its appearance
        // transition before iOS presents the ATT dialog.
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
            ATTrackingManager.requestTrackingAuthorization { _ in
                DispatchQueue.main.async {
                    self.isTrackingAuthorizationRequestInFlight = false
                    // Start AdMob only after the user has responded to ATT,
                    // ensuring the SDK never collects data before consent is given.
                    self.startAdMobSDKIfNeeded()
                    self.flushPendingTrackingCompletions(after: 1.2)
                }
            }
        }
    }

    private func startAdMobSDKIfNeeded() {
        guard !hasStartedAdMob else { return }
        hasStartedAdMob = true
//        GADMobileAds.sharedInstance().requestConfiguration.testDeviceIdentifiers = ["ae454ddf2186e5ac7871bf705de41098"]
        GADMobileAds.sharedInstance().start { [weak self] _ in
            DispatchQueue.main.async {
                self?.homeVC?.loadBannerAd()
            }
        }
    }

    private func startNfcScan(callback: ApduCallback) {
        let beginScan = {
            let api = UnifiedNfcApi()
            api.setCallback(apduCallback: callback)
            api.searchCard()
        }

        if #available(iOS 14, *),
           ATTrackingManager.trackingAuthorizationStatus == .notDetermined,
           isTrackingAuthorizationRequestInFlight {
            pendingTrackingCompletions.append(beginScan)
            return
        }

        requestTrackingAuthorizationIfNeeded(completion: beginScan)
    }

    private func flushPendingTrackingCompletions(after delay: TimeInterval) {
        let completions = pendingTrackingCompletions
        pendingTrackingCompletions.removeAll()
        guard !completions.isEmpty else { return }

        DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
            completions.forEach { $0() }
        }
    }
}
