using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using DotNext;
using Database;

namespace server.Controllers;

/// <summary>
/// 实验控制器
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class ExamController : ControllerBase
{
    private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();

    private readonly ExamManager _examManager;
    private readonly ResourceManager _resourceManager;
    private readonly UserManager _userManager;

    public ExamController(
        ExamManager examManager,
        ResourceManager resourceManager,
        UserManager userManager)
    {
        _examManager = examManager;
        _resourceManager = resourceManager;
        _userManager = userManager;
    }

    /// <summary>
    /// 获取所有实验列表
    /// </summary>
    /// <returns>实验列表</returns>
    [Authorize]
    [HttpGet("list")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(ExamInfo[]), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public IActionResult GetExamList()
    {
        try
        {
            var exams = _examManager.GetAllExams();

            var examInfos = exams.Select(exam => new ExamInfo(exam)).ToArray();

            logger.Info($"成功获取实验列表，共 {examInfos.Length} 个实验");
            return Ok(examInfos);
        }
        catch (Exception ex)
        {
            logger.Error($"获取实验列表时出错: {ex.Message}");
            return StatusCode(StatusCodes.Status500InternalServerError, $"获取实验列表失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 根据实验ID获取实验详细信息
    /// </summary>
    /// <param name="examId">实验ID</param>
    /// <returns>实验详细信息</returns>
    [Authorize]
    [HttpGet("{examId}")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(ExamInfo), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public IActionResult GetExam(string examId)
    {
        if (string.IsNullOrWhiteSpace(examId))
            return BadRequest("实验ID不能为空");

        try
        {
            var result = _examManager.GetExamByID(examId);

            if (!result.IsSuccessful)
            {
                logger.Error($"获取实验时出错: {result.Error.Message}");
                return StatusCode(StatusCodes.Status500InternalServerError, $"获取实验失败: {result.Error.Message}");
            }

            if (!result.Value.HasValue)
            {
                logger.Warn($"实验不存在: {examId}");
                return NotFound($"实验 {examId} 不存在");
            }

            var exam = result.Value.Value;
            var examInfo = new ExamInfo(exam);

            logger.Info($"成功获取实验信息: {examId}");
            return Ok(examInfo);
        }
        catch (Exception ex)
        {
            logger.Error($"获取实验 {examId} 时出错: {ex.Message}");
            return StatusCode(StatusCodes.Status500InternalServerError, $"获取实验失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 创建新实验
    /// </summary>
    /// <param name="request">创建实验请求</param>
    /// <returns>创建结果</returns>
    [Authorize("Admin")]
    [HttpPost("create")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(ExamInfo), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status403Forbidden)]
    [ProducesResponseType(StatusCodes.Status409Conflict)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public IActionResult CreateExam([FromBody] ExamDto request)
    {
        if (string.IsNullOrWhiteSpace(request.ID) || string.IsNullOrWhiteSpace(request.Name) || string.IsNullOrWhiteSpace(request.Description))
            return BadRequest("实验ID、名称和描述不能为空");

        try
        {
            var result = _examManager.CreateExam(request.ID, request.Name, request.Description, request.Tags, request.Difficulty, request.IsVisibleToUsers);

            if (!result.IsSuccessful)
            {
                if (result.Error.Message.Contains("已存在"))
                    return Conflict(result.Error.Message);

                logger.Error($"创建实验时出错: {result.Error.Message}");
                return StatusCode(StatusCodes.Status500InternalServerError, $"创建实验失败: {result.Error.Message}");
            }

            var exam = result.Value;
            var examInfo = new ExamInfo(exam);

            logger.Info($"成功创建实验: {request.ID}");
            return CreatedAtAction(nameof(GetExam), new { examId = request.ID }, examInfo);
        }
        catch (Exception ex)
        {
            logger.Error($"创建实验 {request.ID} 时出错: {ex.Message}");
            return StatusCode(StatusCodes.Status500InternalServerError, $"创建实验失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 更新实验信息
    /// </summary>
    /// <param name="request">更新实验请求</param>
    /// <returns>更新结果</returns>
    [Authorize("Admin")]
    [HttpPost("update")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(ExamInfo), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status403Forbidden)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public IActionResult UpdateExam([FromBody] ExamDto request)
    {
        var examId = request.ID;

        try
        {
            // 首先检查实验是否存在
            var existingExamResult = _examManager.GetExamByID(examId);
            if (!existingExamResult.IsSuccessful)
            {
                logger.Error($"检查实验是否存在时出错: {existingExamResult.Error.Message}");
                return StatusCode(StatusCodes.Status500InternalServerError, $"检查实验失败: {existingExamResult.Error.Message}");
            }

            if (!existingExamResult.Value.HasValue)
            {
                logger.Warn($"要更新的实验不存在: {examId}");
                return NotFound($"实验 {examId} 不存在");
            }

            // 执行更新
            var updateResult = _examManager.UpdateExam(
                examId,
                request.Name,
                request.Description,
                request.Tags,
                request.Difficulty,
                request.IsVisibleToUsers
            );

            if (!updateResult.IsSuccessful)
            {
                logger.Error($"更新实验时出错: {updateResult.Error.Message}");
                return StatusCode(StatusCodes.Status500InternalServerError, $"更新实验失败: {updateResult.Error.Message}");
            }

            // 获取更新后的实验信息并返回
            var updatedExamResult = _examManager.GetExamByID(examId);
            if (!updatedExamResult.IsSuccessful || !updatedExamResult.Value.HasValue)
            {
                logger.Error($"获取更新后的实验信息失败: {examId}");
                return StatusCode(StatusCodes.Status500InternalServerError, "更新成功但获取更新后信息失败");
            }

            var updatedExam = updatedExamResult.Value.Value;
            var examInfo = new ExamInfo(updatedExam);

            logger.Info($"成功更新实验: {examId}，更新记录数: {updateResult.Value}");
            return Ok(examInfo);
        }
        catch (Exception ex)
        {
            logger.Error($"更新实验 {examId} 时出错: {ex.Message}");
            return StatusCode(StatusCodes.Status500InternalServerError, $"更新实验失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 提交作业
    /// </summary>
    /// <param name="examId">实验ID</param>
    /// <param name="file">提交的文件</param>
    /// <returns>提交结果</returns>
    [Authorize]
    [HttpPost("commit/{examId}")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(Resource), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public async Task<IActionResult> SubmitHomework(string examId, IFormFile file)
    {
        if (string.IsNullOrWhiteSpace(examId))
            return BadRequest("实验ID不能为空");

        if (file == null || file.Length == 0)
            return BadRequest("文件不能为空");

        try
        {
            // 获取当前用户信息
            var userName = User.Identity?.Name;
            if (string.IsNullOrEmpty(userName))
                return Unauthorized("无法获取用户信息");

            var userResult = _userManager.GetUserByName(userName);
            if (!userResult.IsSuccessful || !userResult.Value.HasValue)
                return Unauthorized("用户不存在");

            var user = userResult.Value.Value;

            // 检查实验是否存在
            var examResult = _examManager.GetExamByID(examId);
            if (!examResult.IsSuccessful)
            {
                logger.Error($"检查实验是否存在时出错: {examResult.Error.Message}");
                return StatusCode(StatusCodes.Status500InternalServerError, $"检查实验失败: {examResult.Error.Message}");
            }

            if (!examResult.Value.HasValue)
            {
                logger.Warn($"实验不存在: {examId}");
                return NotFound($"实验 {examId} 不存在");
            }

            // 读取文件内容
            byte[] fileData;
            using (var memoryStream = new MemoryStream())
            {
                await file.CopyToAsync(memoryStream);
                fileData = memoryStream.ToArray();
            }

            // 提交作业
            var commitResult = _resourceManager.AddResource(
                user.ID, ResourceTypes.Compression, ResourcePurpose.Homework,
                file.FileName, fileData, examId);
            if (!commitResult.IsSuccessful)
            {
                logger.Error($"提交作业时出错: {commitResult.Error.Message}");
                return StatusCode(StatusCodes.Status500InternalServerError, $"提交作业失败: {commitResult.Error.Message}");
            }

            var commit = commitResult.Value;

            logger.Info($"用户 {userName} 成功提交实验 {examId} 的作业，Commit ID: {commit.ID}");
            return CreatedAtAction(nameof(GetCommitsByExamId), new { examId = examId }, commit);
        }
        catch (Exception ex)
        {
            logger.Error($"提交实验 {examId} 作业时出错: {ex.Message}");
            return StatusCode(StatusCodes.Status500InternalServerError, $"提交作业失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 获取用户在指定实验中的提交记录
    /// </summary>
    /// <param name="examId">实验ID</param>
    /// <returns>提交记录列表</returns>
    [Authorize]
    [HttpGet("commits/{examId}")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(Resource[]), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public IActionResult GetCommitsByExamId(string examId)
    {
        if (string.IsNullOrWhiteSpace(examId))
            return BadRequest("实验ID不能为空");

        try
        {
            // 获取当前用户信息
            var userName = User.Identity?.Name;
            if (string.IsNullOrEmpty(userName))
                return Unauthorized("无法获取用户信息");

            var userResult = _userManager.GetUserByName(userName);
            if (!userResult.IsSuccessful || !userResult.Value.HasValue)
                return Unauthorized("用户不存在");

            var user = userResult.Value.Value;

            // 检查实验是否存在
            var examResult = _examManager.GetExamByID(examId);
            if (!examResult.IsSuccessful)
            {
                logger.Error($"检查实验是否存在时出错: {examResult.Error.Message}");
                return StatusCode(StatusCodes.Status500InternalServerError, $"检查实验失败: {examResult.Error.Message}");
            }

            if (!examResult.Value.HasValue)
            {
                logger.Warn($"实验不存在: {examId}");
                return NotFound($"实验 {examId} 不存在");
            }

            // 获取用户的提交记录
            var commitsResult = _resourceManager.GetResourceListByType(
                ResourceTypes.Compression, ResourcePurpose.Homework, examId);
            if (!commitsResult.IsSuccessful)
            {
                logger.Error($"获取提交记录时出错: {commitsResult.Error.Message}");
                return StatusCode(StatusCodes.Status500InternalServerError, $"获取提交记录失败: {commitsResult.Error.Message}");
            }

            var commits = commitsResult.Value;

            logger.Info($"成功获取用户 {userName} 在实验 {examId} 中的提交记录，共 {commits.Length} 条");
            return Ok(commits);
        }
        catch (Exception ex)
        {
            logger.Error($"获取实验 {examId} 提交记录时出错: {ex.Message}");
            return StatusCode(StatusCodes.Status500InternalServerError, $"获取提交记录失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 删除提交记录
    /// </summary>
    /// <param name="commitId">提交记录ID</param>
    /// <returns>删除结果</returns>
    [Authorize]
    [HttpDelete("commit/{commitId}")]
    [EnableCors("Users")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status403Forbidden)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public IActionResult DeleteCommit(string commitId)
    {
        if (!Guid.TryParse(commitId, out _))
            return BadRequest("提交记录ID格式不正确");

        try
        {
            // 获取当前用户信息
            var userName = User.Identity?.Name;
            if (string.IsNullOrEmpty(userName))
                return Unauthorized("无法获取用户信息");

            var userResult = _userManager.GetUserByName(userName);
            if (!userResult.IsSuccessful || !userResult.Value.HasValue)
                return Unauthorized("用户不存在");

            var user = userResult.Value.Value;

            // 检查是否是管理员
            var isAdmin = user.Permission == UserPermission.Admin;

            // 如果不是管理员，检查提交记录是否属于当前用户
            if (!isAdmin)
            {
                var commitResult = _resourceManager.GetResourceById(commitId);
                if (!commitResult.HasValue)
                {
                    logger.Warn($"提交记录不存在: {commitId}");
                    return NotFound($"提交记录 {commitId} 不存在");
                }

                var commit = commitResult.Value;
                if (commit.UserID != user.ID)
                {
                    logger.Warn($"用户 {userName} 尝试删除不属于自己的提交记录: {commitId}");
                    return Forbid("您只能删除自己的提交记录");
                }
            }

            // 执行删除
            var deleteResult = _resourceManager.DeleteResource(commitId);
            if (!deleteResult)
            {
                logger.Warn($"提交记录不存在: {commitId}");
                return NotFound($"提交记录 {commitId} 不存在");
            }

            logger.Info($"用户 {userName} 成功删除提交记录: {commitId}");
            return Ok($"提交记录 {commitId} 已成功删除");
        }
        catch (Exception ex)
        {
            logger.Error($"删除提交记录 {commitId} 时出错: {ex.Message}");
            return StatusCode(StatusCodes.Status500InternalServerError, $"删除提交记录失败: {ex.Message}");
        }
    }
}

/// <summary>
/// 实验信息
/// </summary>
public class ExamInfo
{
    /// <summary>
    /// 实验的唯一标识符
    /// </summary>
    public string ID { get; set; }

    /// <summary>
    /// 实验名称
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// 实验描述
    /// </summary>
    public string Description { get; set; }

    /// <summary>
    /// 实验创建时间
    /// </summary>
    public DateTime CreatedTime { get; set; }

    /// <summary>
    /// 实验最后更新时间
    /// </summary>
    public DateTime UpdatedTime { get; set; }

    /// <summary>
    /// 实验标签
    /// </summary>
    public string[] Tags { get; set; } = Array.Empty<string>();

    /// <summary>
    /// 实验难度（1-5）
    /// </summary>
    public int Difficulty { get; set; } = 1;

    /// <summary>
    /// 普通用户是否可见
    /// </summary>
    public bool IsVisibleToUsers { get; set; } = true;

    public ExamInfo(Exam exam)
    {
        ID = exam.ID;
        Name = exam.Name;
        Description = exam.Description;
        CreatedTime = exam.CreatedTime;
        UpdatedTime = exam.UpdatedTime;
        Tags = exam.GetTagsList();
        Difficulty = exam.Difficulty;
        IsVisibleToUsers = exam.IsVisibleToUsers;
    }
}

/// <summary>
/// 统一的实验数据传输对象
/// </summary>
public class ExamDto
{
    /// <summary>
    /// 实验的唯一标识符
    /// </summary>
    public required string ID { get; set; }

    /// <summary>
    /// 实验名称
    /// </summary>
    public required string Name { get; set; }

    /// <summary>
    /// 实验描述
    /// </summary>
    public required string Description { get; set; }

    /// <summary>
    /// 实验标签
    /// </summary>
    public string[] Tags { get; set; } = Array.Empty<string>();

    /// <summary>
    /// 实验难度（1-5）
    /// </summary>
    public int Difficulty { get; set; } = 1;

    /// <summary>
    /// 普通用户是否可见
    /// </summary>
    public bool IsVisibleToUsers { get; set; } = true;
}
