import Foundation
import WatchConnectivity

final class WatchConnectivityReceiver: NSObject, @unchecked Sendable {
    private let store: WatchInboxStore
    private let session: WCSession?

    init(store: WatchInboxStore) {
        self.store = store
        if WCSession.isSupported() {
            self.session = WCSession.default
        } else {
            self.session = nil
        }
        super.init()
    }

    func activate() {
        guard let session = self.session else { return }
        session.delegate = self
        session.activate()
    }

    private static func parseNotificationPayload(_ payload: [String: Any]) -> WatchNotifyMessage? {
        guard let type = payload["type"] as? String, type == "watch.notify" else {
            return nil
        }

        let title = (payload["title"] as? String)?
            .trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
        let body = (payload["body"] as? String)?
            .trimmingCharacters(in: .whitespacesAndNewlines) ?? ""

        guard title.isEmpty == false || body.isEmpty == false else {
            return nil
        }

        let id = (payload["id"] as? String)?
            .trimmingCharacters(in: .whitespacesAndNewlines)
        let sentAtMs = (payload["sentAtMs"] as? Int) ?? (payload["sentAtMs"] as? NSNumber)?.intValue

        return WatchNotifyMessage(
            id: id,
            title: title,
            body: body,
            sentAtMs: sentAtMs)
    }
}

extension WatchConnectivityReceiver: WCSessionDelegate {
    func session(
        _: WCSession,
        activationDidCompleteWith _: WCSessionActivationState,
        error _: (any Error)?)
    {}

    func session(_: WCSession, didReceiveMessage message: [String: Any]) {
        guard let incoming = Self.parseNotificationPayload(message) else { return }
        Task { @MainActor in
            self.store.consume(message: incoming, transport: "sendMessage")
        }
    }

    func session(
        _: WCSession,
        didReceiveMessage message: [String: Any],
        replyHandler: @escaping ([String: Any]) -> Void)
    {
        guard let incoming = Self.parseNotificationPayload(message) else {
            replyHandler(["ok": false])
            return
        }
        replyHandler(["ok": true])
        Task { @MainActor in
            self.store.consume(message: incoming, transport: "sendMessage")
        }
    }

    func session(_: WCSession, didReceiveUserInfo userInfo: [String: Any]) {
        guard let incoming = Self.parseNotificationPayload(userInfo) else { return }
        Task { @MainActor in
            self.store.consume(message: incoming, transport: "transferUserInfo")
        }
    }

    func session(_: WCSession, didReceiveApplicationContext applicationContext: [String: Any]) {
        guard let incoming = Self.parseNotificationPayload(applicationContext) else { return }
        Task { @MainActor in
            self.store.consume(message: incoming, transport: "applicationContext")
        }
    }
}
