import Foundation

/// Orpheus tool call event structure
public struct OrpheusToolCallEvent: Codable, Equatable {
    public let toolCallId: String?
    public let toolCallName: String?
    public let data: OrpheusToolCallData?
    
    enum CodingKeys: String, CodingKey {
        case toolCallId = "tool_call_id"
        case toolCallName = "tool_call_name"
        case data
    }
    
    public init(toolCallId: String? = nil, toolCallName: String? = nil, data: OrpheusToolCallData? = nil) {
        self.toolCallId = toolCallId
        self.toolCallName = toolCallName
        self.data = data
    }
}

/// Orpheus tool call data structure
public struct OrpheusToolCallData: Codable, Equatable {
    public let type: String?
    public let messageId: String?
    public let content: JSONValue?
    public let reason: String?
    
    enum CodingKeys: String, CodingKey {
        case type
        case messageId = "message_id"
        case content
        case reason
    }
    
    public init(type: String? = nil, messageId: String? = nil, content: JSONValue? = nil, reason: String? = nil) {
        self.type = type
        self.messageId = messageId
        self.content = content
        self.reason = reason
    }
}

/// Orpheus message event structure
public struct OrpheusMessageEvent: Codable, Equatable {
    public let data: OrpheusMessageData
    
    public init(data: OrpheusMessageData) {
        self.data = data
    }
}

/// Orpheus message data structure
public struct OrpheusMessageData: Codable, Equatable {
    public let type: String?
    public let messageId: String?
    public let content: String?
    public let userId: String?
    public let reason: String?
    public let error: String?
    public let toolCall: JSONValue?
    
    enum CodingKeys: String, CodingKey {
        case type
        case messageId = "message_id"
        case content
        case userId = "user_id"
        case reason
        case error
        case toolCall = "tool_call"
    }
    
    public init(
        type: String? = nil,
        messageId: String? = nil,
        content: String? = nil,
        userId: String? = nil,
        reason: String? = nil,
        error: String? = nil,
        toolCall: JSONValue? = nil
    ) {
        self.type = type
        self.messageId = messageId
        self.content = content
        self.userId = userId
        self.reason = reason
        self.error = error
        self.toolCall = toolCall
    }
}

/// Generate song content structure
public struct GenerateSongContent: Codable, Equatable {
    public let clipIds: [String]
    
    enum CodingKeys: String, CodingKey {
        case clipIds
    }
    
    public init(clipIds: [String] = []) {
        self.clipIds = clipIds
    }
}

/// JSON value wrapper for handling dynamic JSON content
public enum JSONValue: Codable, Equatable {
    case string(String)
    case number(Double)
    case bool(Bool)
    case object([String: JSONValue])
    case array([JSONValue])
    case null
    
    public init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        
        if container.decodeNil() {
            self = .null
        } else if let bool = try? container.decode(Bool.self) {
            self = .bool(bool)
        } else if let number = try? container.decode(Double.self) {
            self = .number(number)
        } else if let string = try? container.decode(String.self) {
            self = .string(string)
        } else if let object = try? container.decode([String: JSONValue].self) {
            self = .object(object)
        } else if let array = try? container.decode([JSONValue].self) {
            self = .array(array)
        } else {
            throw DecodingError.dataCorruptedError(in: container, debugDescription: "Invalid JSON value")
        }
    }
    
    public func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        
        switch self {
        case .string(let value):
            try container.encode(value)
        case .number(let value):
            try container.encode(value)
        case .bool(let value):
            try container.encode(value)
        case .object(let value):
            try container.encode(value)
        case .array(let value):
            try container.encode(value)
        case .null:
            try container.encodeNil()
        }
    }
    
    public func toString() -> String {
        switch self {
        case .string(let str):
            return str
        case .object, .array:
            // For complex objects, return JSON string representation
            if let data = try? JSONEncoder().encode(self),
               let jsonString = String(data: data, encoding: .utf8) {
                return jsonString
            }
            return String(describing: self)
        default:
            return String(describing: self)
        }
    }
}

