import Foundation

enum Role: String, Codable {
    case caller
    case interpreter
}

enum PresenceState: String, Codable {
    case unavailable = "UNAVAILABLE"
    case available = "AVAILABLE"
    case ringing = "RINGING"
    case inCall = "IN_CALL"
}

struct User: Identifiable, Codable, Hashable {
    var id: String { username }
    let username: String
    let role: Role
}

struct CallState: Equatable {
    var callId: String?
    var remoteUser: String?
    var status: CallStatus
    
    enum CallStatus: String {
        case idle
        case calling
        case incoming
        case connecting
        case inCall
        case ending
    }
}

// Signaling Messages
struct SignalingMessage: Codable {
    let type: String
    let callId: String?
    let from: String?
    let to: String?
    let payload: AnyCodable?
}

// Helper for type-erased JSON payload
struct AnyCodable: Codable {
    let value: Any
    
    init(_ value: Any) {
        self.value = value
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if let x = try? container.decode(String.self) { value = x }
        else if let x = try? container.decode(Int.self) { value = x }
        else if let x = try? container.decode(Bool.self) { value = x }
        else if let x = try? container.decode(Double.self) { value = x }
        else if let x = try? container.decode([String: AnyCodable].self) { value = x.mapValues { $0.value } }
        else if let x = try? container.decode([AnyCodable].self) { value = x.map { $0.value } }
        else {
            throw DecodingError.dataCorruptedError(in: container, debugDescription: "AnyCodable value cannot be decoded")
        }
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        if let x = value as? String { try container.encode(x) }
        else if let x = value as? Int { try container.encode(x) }
        else if let x = value as? Int32 { try container.encode(x) } // Added Int32
        else if let x = value as? Bool { try container.encode(x) }
        else if let x = value as? Double { try container.encode(x) }
        else if let x = value as? [String: Any] {
             // Basic support for nested dicts
             let wrapped = x.mapValues { AnyCodable($0) }
             try container.encode(wrapped)
        }
        else if let x = value as? [Any] {
             let wrapped = x.map { AnyCodable($0) }
             try container.encode(wrapped)
        }
        else {
            throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: container.codingPath, debugDescription: "AnyCodable value cannot be encoded"))
        }
    }
}
