//
//  PhoneConnMgr.swift
//  WatchEnd Watch App
//
//  Created by lolli on 2023/9/16.
//

import WatchConnectivity

class PhoneConnMgr: NSObject, WCSessionDelegate, ObservableObject {
    var session: WCSession?
    var _ctx: [String: Any] = [:]
    var ctx: [String: Any] {
        set {
            Store.setCtx(newValue)
            updateUrls(newValue)

            // Notify the view to update, but the [urls] are already published
            // so the view will automatically update when [urls] changes.
            // DispatchQueue.main.async {
            //     self.objectWillChange.send()
            // }
        }
        get {
            return _ctx
        }
    }
    var userInfo: [String: Any] = [:]
    @Published var urls: [String] = []

    override init() {
        super.init()
        if !WCSession.isSupported() {
            print("WCSession not supported")
        }
        session = WCSession.default
        session?.delegate = self
        session?.activate()

        _ctx = Store.getCtx()
        updateUrls(_ctx)
    }

    func updateUrls(_ val: [String: Any]) {
        if let urls = val["urls"] as? [String] {
            DispatchQueue.main.async {
                let list = urls.filter { !$0.isEmpty }
                self.urls = list
                // Save URLs to App Group for widget access
                let appGroupId = "group.com.lollipopkit.toolbox"
                if let defaults = UserDefaults(suiteName: appGroupId) {
                    defaults.set(list, forKey: "watch_shared_urls")
                }
            }
        }
    }

    func session(
        _ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState,
        error: Error?
    ) {
        // Request latest data when the session is activated
        if activationState == .activated {
            requestLatestData()
        }
    }

    // Receive realtime msgs
    func session(_ session: WCSession, didReceiveMessage message: [String: Any]) {
        DispatchQueue.main.async {
            self.ctx = message
        }
    }

    // Receive UserInfo
    func session(_ session: WCSession, didReceiveUserInfo userInfo: [String: Any]) {
        DispatchQueue.main.async {
            self.ctx = userInfo
        }
    }

    // Receive Application Context
    func session(
        _ session: WCSession, didReceiveApplicationContext applicationContext: [String: Any]
    ) {
        DispatchQueue.main.async {
            self.ctx = applicationContext
        }
    }

    private func requestLatestData(timeout: TimeInterval = 5.0, maxRetries: Int = 1) {
        guard let session = session, session.isReachable else { return }

        var didReceiveResponse = false
        var retries = 0

        func sendRequest() {
            session.sendMessage(["action": "requestData"]) { response in
                didReceiveResponse = true
                DispatchQueue.main.async {
                    self.ctx = response
                }
            } errorHandler: { error in
                print("Request data failed: \(error)")
                // Optionally, handle error UI here
            }

            // Timeout handling
            DispatchQueue.main.asyncAfter(deadline: .now() + timeout) { [weak self] in
                guard let self = self else { return }
                if !didReceiveResponse {
                    if retries < maxRetries {
                        retries += 1
                        print("No response, retrying requestLatestData (\(retries))...")
                        sendRequest()
                    } else {
                        print("Request data timed out after \(retries + 1) attempts.")
                        // Optionally, update UI to indicate timeout
                    }
                }
            }
        }

        sendRequest()
    }
}
