import Foundation
import OSLog

/// Handles system-level control messages
/// IMPORTANT: System:ready message handling
/// This handler specifically processes system:ready messages that were previously
/// handled inline. It ensures connection establishment acknowledgment is properly sent.
/// The handler must be registered during app initialization to handle these messages.
@MainActor
final class SystemControlHandler {
    private let logger = Logger(subsystem: BundleIdentifiers.loggerSubsystem, category: "SystemControl")

    // MARK: - Properties

    private let onSystemReady: () -> Void

    // MARK: - Initialization

    init(onSystemReady: @escaping () -> Void = {}) {
        self.onSystemReady = onSystemReady
        logger.info("SystemControlHandler initialized")
        // Note: Registration with SharedUnixSocketManager is handled by
        // SharedUnixSocketManager.initializeSystemHandler()
    }

    // MARK: - Message Handling

    /// Handle incoming system control messages
    func handleMessage(_ data: Data) async -> Data? {
        do {
            // First decode to get the action
            if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any],
               let action = json["action"] as? String
            {
                switch action {
                case "ready":
                    return await handleReadyEvent(data)
                case "ping":
                    return await handlePingRequest(data)
                default:
                    logger.error("Unknown system action: \(action)")
                    return createErrorResponse(for: data, error: "Unknown system action: \(action)")
                }
            } else {
                logger.error("Invalid system message format")
                return createErrorResponse(for: data, error: "Invalid message format")
            }
        } catch {
            logger.error("Failed to parse system message: \(error)")
            return createErrorResponse(for: data, error: "Failed to parse message: \(error.localizedDescription)")
        }
    }

    // MARK: - Action Handlers

    private func handleReadyEvent(_ data: Data) async -> Data? {
        do {
            _ = try ControlProtocol.decode(data, as: ControlProtocol.SystemReadyMessage.self)
            logger.info("System ready event received")

            // Call the ready handler
            onSystemReady()

            // No response needed for events
            return nil
        } catch {
            logger.error("Failed to decode system ready event: \(error)")
            return nil
        }
    }

    private func handlePingRequest(_ data: Data) async -> Data? {
        do {
            let request = try ControlProtocol.decodeSystemPingRequest(data)
            logger.debug("System ping request received")

            let response = ControlProtocol.systemPingResponse(to: request)
            return try ControlProtocol.encode(response)
        } catch {
            logger.error("Failed to handle ping request: \(error)")
            return createErrorResponse(for: data, error: "Failed to process ping: \(error.localizedDescription)")
        }
    }

    // MARK: - Error Handling

    private func createErrorResponse(for data: Data, error: String) -> Data? {
        do {
            // Try to get request ID for proper error response
            if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any],
               let id = json["id"] as? String,
               let action = json["action"] as? String
            {
                // Create error response matching request
                let errorResponse: [String: Any] = [
                    "id": id,
                    "type": "response",
                    "category": "system",
                    "action": action,
                    "error": error
                ]

                return try JSONSerialization.data(withJSONObject: errorResponse)
            }
        } catch {
            logger.error("Failed to create error response: \(error)")
        }

        return nil
    }
}
