import Foundation
import Combine
import WatchConnectivity
import SwiftUI

@MainActor
final class WatchConnectivityProvider: NSObject, ObservableObject {
    static let shared = WatchConnectivityProvider()

    @Published var timetableEvents: [WatchTimetableEvent] = []
    @Published var selectedProgram: String = ""
    @Published var lastUpdated: Date?

    private override init() {
        super.init()
        if WCSession.isSupported() {
            WCSession.default.delegate = self
            WCSession.default.activate()
        }
    }

    func requestUpdate() {
        let session = WCSession.default

        if !session.receivedApplicationContext.isEmpty {
            handleContext(session.receivedApplicationContext)
        }

        guard session.activationState == .activated, session.isReachable else { return }
        session.sendMessage(
            ["request": "timetable"],
            replyHandler: { [weak self] reply in
                Task { @MainActor in
                    self?.handleContext(reply)
                }
            },
            errorHandler: nil
        )
    }
}

extension WatchConnectivityProvider: WCSessionDelegate {
    nonisolated func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
        Task { @MainActor in
            guard !session.receivedApplicationContext.isEmpty else { return }
            self.handleContext(session.receivedApplicationContext)
        }
    }

    #if os(iOS)
    nonisolated func sessionDidBecomeInactive(_ session: WCSession) {}

    nonisolated func sessionDidDeactivate(_ session: WCSession) {}
    #endif

    nonisolated func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String: Any]) {
        Task { @MainActor in
            self.handleContext(applicationContext)
        }
    }

    nonisolated func session(_ session: WCSession, didReceiveMessage message: [String: Any]) {
        Task { @MainActor in
            self.handleContext(message)
        }
    }

    @MainActor
    private func handleContext(_ context: [String: Any]) {
        if let data = context["events"] as? Data,
           let events = try? JSONDecoder().decode([WatchTimetableEvent].self, from: data) {
            timetableEvents = events.sorted(by: { $0.startDate < $1.startDate })
            lastUpdated = Date()
        }
        if let program = context["program"] as? String {
            selectedProgram = program
        }
    }
}
