using Serilog;

namespace GeViScopeBridge.SDK
{
    /// <summary>
    /// Dispatches SDK actions to GeViServer
    /// </summary>
    public class ActionDispatcher
    {
        private readonly GeViDatabaseWrapper _dbWrapper;
        private readonly ILogger _logger;

        public ActionDispatcher(GeViDatabaseWrapper dbWrapper, ILogger logger)
        {
            _dbWrapper = dbWrapper ?? throw new ArgumentNullException(nameof(dbWrapper));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }

        /// <summary>
        /// Execute cross-switch operation
        /// Routes video from camera (input) to monitor (output)
        /// </summary>
        /// <param name="cameraId">Video input channel</param>
        /// <param name="monitorId">Video output channel</param>
        /// <param name="mode">Switch mode (0 = normal)</param>
        public async Task<bool> ExecuteCrossSwitchAsync(int cameraId, int monitorId, int mode = 0)
        {
            if (!await _dbWrapper.EnsureConnectedAsync())
            {
                throw new InvalidOperationException("Not connected to GeViServer");
            }

            try
            {
                // Format: CrossSwitch(VideoInput, VideoOutput, SwitchMode)
                string action = $"CrossSwitch({cameraId}, {monitorId}, {mode})";
                _logger.Information("Executing cross-switch: Camera {CameraId} → Monitor {MonitorId}, Mode {Mode}",
                    cameraId, monitorId, mode);

                bool success = await _dbWrapper.SendMessageAsync(action);

                if (success)
                {
                    _logger.Information("Cross-switch executed successfully");
                }
                else
                {
                    _logger.Warning("Cross-switch execution failed");
                }

                return success;
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "Failed to execute cross-switch");
                throw;
            }
        }

        /// <summary>
        /// Clear video output (stop displaying video on monitor)
        /// </summary>
        /// <param name="monitorId">Video output channel to clear</param>
        public async Task<bool> ClearMonitorAsync(int monitorId)
        {
            if (!await _dbWrapper.EnsureConnectedAsync())
            {
                throw new InvalidOperationException("Not connected to GeViServer");
            }

            try
            {
                // Format: ClearVideoOutput(VideoOutput)
                string action = $"ClearVideoOutput({monitorId})";
                _logger.Information("Clearing monitor {MonitorId}", monitorId);

                bool success = await _dbWrapper.SendMessageAsync(action);

                if (success)
                {
                    _logger.Information("Monitor cleared successfully");
                }
                else
                {
                    _logger.Warning("Monitor clear operation failed");
                }

                return success;
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "Failed to clear monitor");
                throw;
            }
        }

        /// <summary>
        /// Execute custom SDK action (generic)
        /// </summary>
        /// <param name="action">Action string (e.g., "CrossSwitch(1, 2, 0)")</param>
        public async Task<bool> ExecuteActionAsync(string action)
        {
            if (string.IsNullOrWhiteSpace(action))
            {
                throw new ArgumentException("Action cannot be null or empty", nameof(action));
            }

            if (!await _dbWrapper.EnsureConnectedAsync())
            {
                throw new InvalidOperationException("Not connected to GeViServer");
            }

            try
            {
                _logger.Information("Executing custom action: {Action}", action);
                bool success = await _dbWrapper.SendMessageAsync(action);

                if (success)
                {
                    _logger.Information("Custom action executed successfully");
                }
                else
                {
                    _logger.Warning("Custom action execution failed");
                }

                return success;
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "Failed to execute custom action");
                throw;
            }
        }
    }
}
