//
//  WebSocketManager.swift
//  AcaMate
//
//  Created by TAnine on 2/17/25.
//

import Foundation
import Combine

import Starscream

// SignalR은 메세지의 끝이 \u{1E} 해당 유니코드 문자를 원함
class WebSocketManager: ObservableObject ,WebSocketDelegate {
    
    @Published var socket: WebSocket?
    @Published var receivedMessage: [String] = []
    
    init() {
        guard let url = URL(string: "\(WS_URL)/chatHub?transport=webSockets") else { return }
        var request = URLRequest(url: url)
        request.timeoutInterval = 5
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.setValue("Upgrade", forHTTPHeaderField: "Connection")
        
        socket = WebSocket(request: request)
        socket?.delegate = self
    }
    
    func connect() {
        printLog("TRY CONNECT SOCKET")
        socket?.connect()
    }
    
    func didReceive(event: Starscream.WebSocketEvent, client: WebSocketClient) {
        switch event {
        case .connected(let header):
            printLog("CONNECTED : \(header)")
            // 우리는 현재 JSON기반으로 메시지를 주고 받을거고 SignalR JSON 프로토콜의 버전은 1이다
            let handShakeMsg =
            """
            {
                "protocol":"json",
                "version":1
            }\u{1E}
            """
            self.socket?.write(string: handShakeMsg)
            
        case .disconnected(let reason, let code):
            printLog("❌ DISCONNECTED: [\(code)] - \(reason)")
            
        case .error(let error):
            printLog("🆘 SOCKET ERROR: \(error?.localizedDescription ?? "unknown")")
            
        case .text(let text):
            // 서버에서 메세지를 보내면 여기로 들어올거고
            // 받아온 텍스트의 앞은 target, [sendet, message] 순서로 들어온다.
            printLog("📩 SERVER SENT: \(text)")
            
            if let data = try? JSONSerialization.jsonObject(with: Data(text.utf8)) as? [String: Any],
               let target = data["target"] as? String,
               let args = data["arguments"] as? [String] {
                
                if target == "ReceiveMessage" {
                    let sender = args[0]
                    let message = args[1]
                    receivedMessage.append(message)
                    print("💬 [\(sender)] \(message)")
                }
            }
            
            
            
            
            
            
        case .binary(let binary):
            printLog("BINARY?: \(binary)")
            
        case .cancelled:
            printLog("SOCKET CONNECTED CANCELLED!!!")
            
        default:
            break
        }
    }
    
    
    func disconnect() {
        socket?.disconnect()
        socket?.delegate = nil  // 추가: delegate 해제
        socket = nil            // 필요시, 소켓 객체 해제
        printLog("CLOSE SOCKET")
    }
    
    func sendMessage(_ message: String) {
        let json = """
        {
            "type": 1,
            "target":"SendMessage",
            "arguments":["iOS", "\(message)"]
        }\u{1E}
        """
        socket?.write(string: json)
        printLog("SEND THE MESSAGE: \(message)")
    }
    
    func joinRoom(_ cid: String){
        let json = """
            {
                "type": 1,
                "target":"JoinRoom",
                "arguments":["\(cid)"]
            }\u{1E}
            """
        socket?.write(string: json)
        printLog("JOIN: \(cid)")
    }
}
