using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using System.Security.Claims;
using DotNext;
using server.Services;

/// <summary>
/// 视频流控制器，支持动态配置摄像头连接
/// </summary>
[ApiController]
[Authorize]
[EnableCors("Users")]
[Route("api/[controller]")]
public class VideoStreamController : ControllerBase
{
    private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();

    private readonly HttpVideoStreamService _videoStreamService;
    private readonly Database.UserManager _userManager;

    public class AvailableResolutionsResponse
    {
        public int Width { get; set; }
        public int Height { get; set; }
        public string Name { get; set; } = string.Empty;
        public string Value => $"{Width}x{Height}";
    }

    /// <summary>
    /// 初始化HTTP视频流控制器
    /// </summary>
    /// <param name="videoStreamService">HTTP视频流服务</param>
    /// <param name="userManager">用户管理服务</param>
    public VideoStreamController(
        HttpVideoStreamService videoStreamService, Database.UserManager userManager)
    {
        logger.Info("创建VideoStreamController，命名空间：{Namespace}", this.GetType().Namespace);
        _videoStreamService = videoStreamService;
        _userManager = userManager;
    }

    private Optional<string> TryGetBoardId()
    {
        var userName = User.FindFirstValue(ClaimTypes.Name);
        if (string.IsNullOrEmpty(userName))
        {
            logger.Error("User name not found in claims.");
            return Optional<string>.None;
        }

        var userRet = _userManager.GetUserByName(userName);
        if (!userRet.IsSuccessful || !userRet.Value.HasValue)
        {
            logger.Error("User not found.");
            return Optional<string>.None;
        }

        var user = userRet.Value.Value;
        var boardId = user.BoardID;
        if (boardId == Guid.Empty)
        {
            logger.Error("No board bound to this user.");
            return Optional<string>.None;
        }

        return boardId.ToString();
    }

    private Optional<string> TryGetBoardId()
    {
        var userName = User.FindFirstValue(ClaimTypes.Name);
        if (string.IsNullOrEmpty(userName))
        {
            logger.Error("User name not found in claims.");
            return Optional<string>.None;
        }

        var db = new AppDataConnection();
        if (db == null)
        {
            logger.Error("Database connection failed.");
            return Optional<string>.None;
        }

        var userRet = db.GetUserByName(userName);
        if (!userRet.IsSuccessful || !userRet.Value.HasValue)
        {
            logger.Error("User not found.");
            return Optional<string>.None;
        }

        var user = userRet.Value.Value;
        var boardId = user.BoardID;
        if (boardId == Guid.Empty)
        {
            logger.Error("No board bound to this user.");
            return Optional<string>.None;
        }

        return boardId.ToString();
    }

    /// <summary>
    /// 获取 HTTP 视频流服务状态
    /// </summary>
    /// <returns>服务状态信息</returns>
    [HttpGet("ServiceStatus")]
    [ProducesResponseType(typeof(VideoStreamServiceStatus), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
    public IResult GetServiceStatus()
    {
        try
        {
            // 使用HttpVideoStreamService提供的状态信息
            var status = _videoStreamService.GetServiceStatus();

            // 转换为小写首字母的JSON属性（符合前端惯例）
            return TypedResults.Ok(status);
        }
        catch (Exception ex)
        {
            logger.Error(ex, "获取 HTTP 视频流服务状态失败");
            return TypedResults.InternalServerError(ex.Message);
        }
    }

    [HttpGet("MyEndpoint")]
    [ProducesResponseType(typeof(VideoStreamEndpoint), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
    public IResult MyEndpoint()
    {
        try
        {
            var boardId = TryGetBoardId().OrThrow(() => new Exception("Board ID not found"));
            var endpoint = _videoStreamService.GetVideoEndpoint(boardId);

            return TypedResults.Ok(endpoint);
        }
        catch (Exception ex)
        {
            logger.Error(ex, "获取摄像头配置失败");
            return TypedResults.InternalServerError(ex.Message);
        }
    }

    /// <summary>
    /// 测试 HTTP 视频流连接
    /// </summary>
    /// <returns>连接测试结果</returns>
    [HttpPost("TestConnection")]
    [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
    public async Task<IResult> TestConnection()
    {
        try
        {
            var boardId = TryGetBoardId().OrThrow(() => new Exception("Board ID not found"));
            var endpoint = _videoStreamService.GetVideoEndpoint(boardId);

            // 尝试通过HTTP请求检查视频流服务是否可访问
            bool isConnected = false;
            using (var httpClient = new HttpClient())
            {
                httpClient.Timeout = TimeSpan.FromSeconds(2); // 设置较短的超时时间
                var response = await httpClient.GetAsync(endpoint.MjpegUrl);

                // 只要能连接上就认为成功，不管返回状态
                isConnected = response.IsSuccessStatusCode;
            }

            var ret = await _videoStreamService.TestCameraConnection(boardId);

            return TypedResults.Ok(ret);
        }
        catch (Exception ex)
        {
            logger.Error(ex, "HTTP 视频流连接测试失败");
            // 连接失败但不抛出异常，而是返回连接失败的结果
            return TypedResults.Ok(false);
        }
    }

    [HttpPost("SetVideoStreamEnable")]
    [ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(string), StatusCodes.Status500InternalServerError)]
    public async Task<IActionResult> SetVideoStreamEnable(bool enable)
    {
        try
        {
            var boardId = TryGetBoardId().OrThrow(() => new ArgumentException("Board ID is required"));

            await _videoStreamService.SetVideoStreamEnableAsync(boardId.ToString(), enable);
            return Ok($"HDMI transmission for board {boardId} disabled.");
        }
        catch (Exception ex)
        {
            logger.Error(ex, $"Failed to disable HDMI transmission for board");
            return StatusCode(500, $"Error disabling HDMI transmission: {ex.Message}");
        }
    }

    /// <summary>
    /// 设置视频流分辨率
    /// </summary>
    /// <param name="request">分辨率配置请求</param>
    /// <returns>设置结果</returns>
    [HttpPost("Resolution")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(string), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(string), StatusCodes.Status500InternalServerError)]
    public async Task<IResult> SetResolution([FromBody] ResolutionConfigRequest request)
    {
        try
        {
            var boardId = TryGetBoardId().OrThrow(() => new Exception("Board ID not found"));

            var ret = await _videoStreamService.SetResolutionAsync(boardId, request.Width, request.Height);

            if (ret.IsSuccessful && ret.Value)
            {
                return TypedResults.Ok(new
                {
                    success = true,
                    message = $"成功设置分辨率为 {request.Width}x{request.Height}",
                    width = request.Width,
                    height = request.Height,
                    timestamp = DateTime.Now
                });
            }
            else
            {
                return TypedResults.BadRequest(new
                {
                    success = false,
                    message = ret.Error?.ToString() ?? "未知错误",
                    timestamp = DateTime.Now
                });
            }
        }
        catch (Exception ex)
        {
            logger.Error(ex, $"设置分辨率为 {request.Width}x{request.Height} 失败");
            return TypedResults.InternalServerError($"设置分辨率失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 获取支持的分辨率列表
    /// </summary>
    /// <returns>支持的分辨率列表</returns>
    [HttpGet("SupportedResolutions")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(AvailableResolutionsResponse[]), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(string), StatusCodes.Status500InternalServerError)]
    public IResult GetSupportedResolutions()
    {
        // (640, 480, "640x480 (VGA)"),
        // (960, 540, "960x540 (qHD)"),
        // (1280, 720, "1280x720 (HD)"),
        // (1280, 960, "1280x960 (SXGA)"),
        // (1920, 1080, "1920x1080 (Full HD)")
        return TypedResults.Ok(new AvailableResolutionsResponse[]
        {
            new AvailableResolutionsResponse { Width = 640, Height = 480, Name = "640x480(VGA)" },
            new AvailableResolutionsResponse { Width = 960, Height = 480, Name = "960x480(qHD)" },
            new AvailableResolutionsResponse { Width = 1280, Height = 720, Name = "1280x720(HD)" },
            new AvailableResolutionsResponse { Width = 1280, Height = 960, Name = "1280x960(SXGA)" },
            new AvailableResolutionsResponse { Width = 1920, Height = 1080, Name = "1920x1080(Full HD)" }
        });
    }

    /// <summary>
    /// 初始化摄像头自动对焦功能
    /// </summary>
    /// <returns>初始化结果</returns>
    [HttpPost("InitAutoFocus")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(object), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(string), StatusCodes.Status500InternalServerError)]
    public async Task<IResult> InitAutoFocus()
    {
        try
        {
            var boardId = TryGetBoardId().OrThrow(() => new Exception("Board ID not found"));

            var result = await _videoStreamService.InitAutoFocusAsync(boardId);

            if (result)
            {
                logger.Info("自动对焦初始化成功");
                return TypedResults.Ok(new
                {
                    success = true,
                    message = "自动对焦初始化成功",
                    timestamp = DateTime.Now
                });
            }
            else
            {
                logger.Warn("自动对焦初始化失败");
                return TypedResults.BadRequest(new
                {
                    success = false,
                    message = "自动对焦初始化失败",
                    timestamp = DateTime.Now
                });
            }
        }
        catch (Exception ex)
        {
            logger.Error(ex, "初始化自动对焦时发生异常");
            return TypedResults.InternalServerError($"初始化自动对焦失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 执行自动对焦
    /// </summary>
    /// <returns>对焦结果</returns>
    [HttpPost("AutoFocus")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(object), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(string), StatusCodes.Status500InternalServerError)]
    public async Task<IResult> AutoFocus()
    {
        try
        {
            var boardId = TryGetBoardId().OrThrow(() => new Exception("Board ID not found"));

            var result = await _videoStreamService.PerformAutoFocusAsync(boardId);

            if (result)
            {
                logger.Info("自动对焦执行成功");
                return TypedResults.Ok(new
                {
                    success = true,
                    message = "自动对焦执行成功",
                    timestamp = DateTime.Now
                });
            }
            else
            {
                logger.Warn("自动对焦执行失败");
                return TypedResults.BadRequest(new
                {
                    success = false,
                    message = "自动对焦执行失败",
                    timestamp = DateTime.Now
                });
            }
        }
        catch (Exception ex)
        {
            logger.Error(ex, "执行自动对焦时发生异常");
            return TypedResults.InternalServerError($"执行自动对焦失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 配置摄像头连接参数
    /// </summary>
    /// <returns>配置结果</returns>
    [HttpPost("ConfigureCamera")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(object), StatusCodes.Status400BadRequest)]
    [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
    public async Task<IResult> ConfigureCamera()
    {
        try
        {
            var boardId = TryGetBoardId().OrThrow(() => new Exception("Board ID not found"));

            var ret = await _videoStreamService.ConfigureCameraAsync(boardId);

            if (ret)
            {
                return TypedResults.Ok(new { Message = "配置成功" });
            }
            else
            {
                return TypedResults.BadRequest(new { Message = "配置失败" });
            }
        }
        catch (Exception ex)
        {
            logger.Error(ex, "配置摄像头连接失败");
            return TypedResults.InternalServerError(ex.Message);
        }
    }

    /// <summary>
    /// 分辨率配置请求模型
    /// </summary>
    public class ResolutionConfigRequest
    {
        /// <summary>
        /// 宽度
        /// </summary>
        [Required]
        [Range(640, 1920, ErrorMessage = "宽度必须在640-1920范围内")]
        public int Width { get; set; }

        /// <summary>
        /// 高度
        /// </summary>
        [Required]
        [Range(480, 1080, ErrorMessage = "高度必须在480-1080范围内")]
        public int Height { get; set; }
    }

    public class AvailableResolutionsResponse
    {
        public int Width { get; set; }
        public int Height { get; set; }
        public string Name { get; set; } = string.Empty;
        public string Value => $"{Width}x{Height}";
    }
}
