using Grpc.Core;
using GeViScopeBridge.Protos;
using GeViScopeBridge.SDK;
using GeViScopeBridge.Utils;
using Serilog;

namespace GeViScopeBridge.Services
{
    /// <summary>
    /// gRPC service for camera (video input) operations
    /// </summary>
    public class CameraServiceImplementation : CameraService.CameraServiceBase
    {
        private readonly StateQueryHandler _stateQuery;
        private readonly ILogger _logger;

        public CameraServiceImplementation(StateQueryHandler stateQuery, ILogger logger)
        {
            _stateQuery = stateQuery ?? throw new ArgumentNullException(nameof(stateQuery));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }

        /// <summary>
        /// List all cameras (video inputs)
        /// </summary>
        public override async Task<ListCamerasResponse> ListCameras(
            ListCamerasRequest request,
            ServerCallContext context)
        {
            try
            {
                _logger.Information("ListCameras called");

                var cameras = await _stateQuery.EnumerateCamerasAsync();

                var response = new ListCamerasResponse
                {
                    TotalCount = cameras.Count
                };

                foreach (var camera in cameras)
                {
                    response.Cameras.Add(new CameraInfo
                    {
                        Id = camera.Id,
                        Name = camera.Name,
                        Description = camera.Description,
                        HasPtz = camera.HasPTZ,
                        HasVideoSensor = camera.HasVideoSensor,
                        Status = camera.Status,
                        LastSeen = new Timestamp
                        {
                            Seconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
                            Nanos = 0
                        }
                    });
                }

                _logger.Information("ListCameras completed: {Count} cameras", cameras.Count);
                return response;
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "Failed to list cameras");
                throw ErrorTranslator.CreateRpcException(ex, "Failed to list cameras");
            }
        }

        /// <summary>
        /// Get detailed information about a specific camera
        /// </summary>
        public override async Task<CameraInfo> GetCamera(
            GetCameraRequest request,
            ServerCallContext context)
        {
            try
            {
                _logger.Information("GetCamera called for camera {CameraId}", request.CameraId);

                // Enumerate all cameras and find the requested one
                var cameras = await _stateQuery.EnumerateCamerasAsync();
                var camera = cameras.FirstOrDefault(c => c.Id == request.CameraId);

                if (camera == null)
                {
                    throw new RpcException(new Status(StatusCode.NotFound,
                        $"Camera with ID {request.CameraId} not found"));
                }

                var response = new CameraInfo
                {
                    Id = camera.Id,
                    Name = camera.Name,
                    Description = camera.Description,
                    HasPtz = camera.HasPTZ,
                    HasVideoSensor = camera.HasVideoSensor,
                    Status = camera.Status,
                    LastSeen = new Timestamp
                    {
                        Seconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
                        Nanos = 0
                    }
                };

                _logger.Information("GetCamera completed for camera {CameraId}", request.CameraId);
                return response;
            }
            catch (RpcException)
            {
                throw;  // Re-throw RpcExceptions as-is
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "Failed to get camera {CameraId}", request.CameraId);
                throw ErrorTranslator.CreateRpcException(ex, "Failed to get camera");
            }
        }
    }
}
