import Foundation
import Combine

class SignalingService: ObservableObject {
    private var webSocketTask: URLSessionWebSocketTask?
    private let urlSession = URLSession(configuration: .default)
    private var serverUrl: URL {
        let ip = UserDefaults.standard.string(forKey: "server_ip") ?? "192.168.1.199"
        return URL(string: "ws://\(ip):8080")!
    }
    
    // Publishers for ViewModel to subscribe to
    let messageReceived = PassthroughSubject<SignalingMessage, Never>()
    let isConnected = CurrentValueSubject<Bool, Never>(false)
    
    func connect() {
        print("Connecting to \(serverUrl)...")
        webSocketTask = urlSession.webSocketTask(with: serverUrl)
        webSocketTask?.resume()
        isConnected.send(true) // Optimistic, usually handle with delegate or ping
        
        receiveMessage()
    }
    
    func disconnect() {
        webSocketTask?.cancel(with: .normalClosure, reason: nil)
        isConnected.send(false)
    }
    
    func send(_ message: SignalingMessage) {
        do {
            let data = try JSONEncoder().encode(message)
            let message = URLSessionWebSocketTask.Message.data(data)
            webSocketTask?.send(message) { error in
                if let error = error {
                    print("Error sending message: \(error)")
                }
            }
        } catch {
            print("Error encoding message: \(error)")
        }
    }
    
    private func receiveMessage() {
        webSocketTask?.receive { [weak self] result in
            guard let self = self else { return }
            
            switch result {
            case .failure(let error):
                print("Error receiving message: \(error)")
                self.isConnected.send(false) 
                // In production, implement reconnect logic here
                
            case .success(let message):
                switch message {
                case .string(let text):
                    self.handleMessageData(text.data(using: .utf8))
                case .data(let data):
                    self.handleMessageData(data)
                @unknown default:
                    break
                }
                
                // Continue receiving messages
                self.receiveMessage()
            }
        }
    }
    
    private func handleMessageData(_ data: Data?) {
        guard let data = data else { return }
        do {
            let message = try JSONDecoder().decode(SignalingMessage.self, from: data)
            DispatchQueue.main.async {
                self.messageReceived.send(message)
            }
        } catch {
            print("Failed to decode message: \(error)")
            if let str = String(data: data, encoding: .utf8) {
                print("Raw message: \(str)")
            }
        }
    }
}
