import Foundation

/// Processes real-time events and converts them into session events.
///
/// This component takes raw real-time events, processes them through handlers,
/// and converts the handler results into session events that can be dispatched to the store.
public struct OrpheusRealtimeEventProcessor {
    private let messageContentHandler: MessageContentHandler
    private let messageToolCallHandler: MessageToolCallHandler
    private let messageFinishedHandler: MessageFinishedHandler
    private let messageErrorHandler: MessageErrorHandler
    private let toolCallContentHandler: ToolCallContentHandler
    private let toolCallResultHandler: ToolCallResultHandler
    private let toolCallFailureHandler: ToolCallFailureHandler
    
    public init(
        messageContentHandler: MessageContentHandler,
        messageToolCallHandler: MessageToolCallHandler,
        messageFinishedHandler: MessageFinishedHandler,
        messageErrorHandler: MessageErrorHandler,
        toolCallContentHandler: ToolCallContentHandler,
        toolCallResultHandler: ToolCallResultHandler,
        toolCallFailureHandler: ToolCallFailureHandler
    ) {
        self.messageContentHandler = messageContentHandler
        self.messageToolCallHandler = messageToolCallHandler
        self.messageFinishedHandler = messageFinishedHandler
        self.messageErrorHandler = messageErrorHandler
        self.toolCallContentHandler = toolCallContentHandler
        self.toolCallResultHandler = toolCallResultHandler
        self.toolCallFailureHandler = toolCallFailureHandler
    }
    
    /// Processes a real-time event synchronously and returns a session event to dispatch.
    /// This matches Android's approach where events are processed synchronously to avoid race conditions.
    /// Handlers perform synchronous transformations only. Any async work (e.g., fetching data from APIs)
    /// should be handled separately in the repository layer via clipIdsToFetch.
    public func processEvent(
        event: OrpheusRealtimeEvent,
        session: OrpheusSession
    ) -> OrpheusSessionEvent {
        switch event {
        case .connected:
            print("📡 Connected to realtime service")
            return .noOp
            
        case .disconnected:
            print("📡 Disconnected from realtime service")
            return .noOp
            
        case .error(let error):
            print("❌ Realtime event error: \(error)")
            return .noOp
            
        case .messageContent:
            let result = messageContentHandler.handle(event: event, session: session)
            return processHandlerResult(result, session: session)
            
        case .messageToolCall:
            let result = messageToolCallHandler.handle(event: event, session: session)
            return processHandlerResult(result, session: session)
            
        case .messageFinished:
            let result = messageFinishedHandler.handle(event: event, session: session)
            return processHandlerResult(result, session: session)
            
        case .messageError:
            let result = messageErrorHandler.handle(event: event, session: session)
            return processHandlerResult(result, session: session)
            
        case .toolCallContent:
            let result = toolCallContentHandler.handle(event: event, session: session)
            return processHandlerResult(result, session: session)
            
        case .toolCallResult:
            let result = toolCallResultHandler.handle(event: event, session: session)
            return processHandlerResult(result, session: session)
            
        case .toolCallFailure:
            let result = toolCallFailureHandler.handle(event: event, session: session)
            return processHandlerResult(result, session: session)
        }
    }
    
    private func processHandlerResult(_ result: EventHandlerResult, session: OrpheusSession) -> OrpheusSessionEvent {
        switch result {
        case .messagesUpdated(let updatedMessages):
            return .messagesReplaced(updatedMessages)
            
        case .updateMessage(let messageId, let transform, let clipIdsToFetch):
            // Apply transform to get updated message
            guard let messageIndex = session.messages.firstIndex(where: { $0.id == messageId }) else {
                print("⚠️ Message not found for update: \(messageId)")
                return .noOp
            }
            let updatedMessage = transform(session.messages[messageIndex])
            return .messageUpdated(messageId: messageId, message: updatedMessage, clipIdsToFetch: clipIdsToFetch)
            
        case .noOp:
            return .noOp
        }
    }
}

