//  ChottuLinkDeepLinkHook.swift
//  Correctly swizzles UnityAppController to intercept deep links.

import UIKit
import ObjectiveC
import ChottuLinkSDK

// The C symbol 'cl_resolveLink' is defined in the other plugin file, ChottuLink.swift,
// so it does not need to be redeclared here.

@MainActor private func forward(_ url: URL) {
    if ChottuLinkBootstrap.isInitialized {
        ChottuLink.handleLink(url)
    } else {
        // Buffer until cl_init runs
        ChottuLinkBootstrap.pendingLaunchURL = url
    }
}

// C-exported function, called from C# at startup to trigger the swizzling.
@_cdecl("cl_bootstrap_deeplink_hook")
public func cl_bootstrap_deeplink_hook() {
    performOnMain {
        UnityAppController.swizzleDeepLinkHandlers()
    }
}


@objc extension UnityAppController {

    private static var hasSwizzled = false

    static func swizzleDeepLinkHandlers() {
        guard !hasSwizzled else { return }
        hasSwizzled = true

        let cls: AnyClass = UnityAppController.self

        // Swizzle for custom URL schemes: application(_:open:options:)
        let originalSelector1 = #selector(UIApplicationDelegate.application(_:open:options:))
        let swizzledSelector1 = #selector(cl_swizzled_application(_:open:options:))

        if let originalMethod = class_getInstanceMethod(cls, originalSelector1),
           let swizzledMethod = class_getInstanceMethod(cls, swizzledSelector1) {
            method_exchangeImplementations(originalMethod, swizzledMethod)
        }

        // Swizzle for universal links: application(_:continue:restorationHandler:)
        let originalSelector2 = #selector(UIApplicationDelegate.application(_:continue:restorationHandler:))
        let swizzledSelector2 = #selector(cl_swizzled_application(_:continue:restorationHandler:))

        if let originalMethod = class_getInstanceMethod(cls, originalSelector2),
           let swizzledMethod = class_getInstanceMethod(cls, swizzledSelector2) {
            method_exchangeImplementations(originalMethod, swizzledMethod)
        }

        // Swizzle for cold-start delivery: application(_:didFinishLaunchingWithOptions:)
        let originalSelector3 = #selector(UIApplicationDelegate.application(_:didFinishLaunchingWithOptions:))
        let swizzledSelector3 = #selector(cl_swizzled_application(_:didFinishLaunchingWithOptions:))

        if let originalMethod = class_getInstanceMethod(cls, originalSelector3),
           let swizzledMethod = class_getInstanceMethod(cls, swizzledSelector3) {
            method_exchangeImplementations(originalMethod, swizzledMethod)
        }
    }

    // MARK: - Swizzled Method Implementations

    @objc func cl_swizzled_application(_ app: UIApplication,
                                       open url: URL,
                                       options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        // 1. Forward the URL to our handler
        forward(url)
        
        // 2. Call the ORIGINAL implementation of application(_:open:options:)
        //    (This is NOT recursive, as the method implementations have been swapped)
        return self.cl_swizzled_application(app, open: url, options: options)
    }

    @objc func cl_swizzled_application(_ application: UIApplication,
                                       continue userActivity: NSUserActivity,
                                       restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
        // 1. Forward the URL to our handler
        if let url = userActivity.webpageURL {
            forward(url)
        }

        // 2. Call the ORIGINAL implementation of application(_:continue:restorationHandler:)
        return self.cl_swizzled_application(application, continue: userActivity, restorationHandler: restorationHandler)
    }

    @objc func cl_swizzled_application(_ application: UIApplication,
                                        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        // Handle custom URL scheme on cold start
        if let url = launchOptions?[.url] as? URL {
            forward(url)
        }

        // Handle universal link on cold start via userActivity dictionary
        if let dict = launchOptions?[.userActivityDictionary] as? [AnyHashable: Any] {
            // Known key in the dictionary
            if let userActivity = dict["UIApplicationLaunchOptionsUserActivityKey"] as? NSUserActivity,
               let url = userActivity.webpageURL {
                forward(url)
            }
        }

        return self.cl_swizzled_application(application, didFinishLaunchingWithOptions: launchOptions)
    }
}

// C-callable bridge used by ChottuLinkUnity6SceneHook.mm to forward URLs from
// UIWindowSceneDelegate into the same forward() + buffering state machine.
@_cdecl("cl_forward_url_string")
public func cl_forward_url_string(_ urlCString: UnsafePointer<CChar>?) {
    guard let cStr = urlCString, let url = URL(string: String(cString: cStr)) else { return }
    performOnMain {
        forward(url)
    }
}
