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

namespace server.Controllers;

/// <summary>
/// 资源控制器 - 提供统一的资源管理API
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class ResourceController : ControllerBase
{
    private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();

    private readonly UserManager _userManager;
    private readonly ResourceManager _resourceManager;

    public ResourceController(UserManager userManager, ResourceManager resourceManager)
    {
        _userManager = userManager;
        _resourceManager = resourceManager;
    }

    /// <summary>
    /// 添加资源（文件上传）
    /// </summary>
    /// <param name="request">添加资源请求</param>
    /// <param name="file">资源文件</param>
    /// <returns>添加结果</returns>
    [Authorize]
    [HttpPost]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(ResourceInfo), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public async Task<IActionResult> AddResource([FromForm] AddResourceRequest request, IFormFile file)
    {
        if (string.IsNullOrWhiteSpace(request.ResourceType) || file == null)
            return BadRequest("资源类型、资源用途和文件不能为空");

        // 验证资源用途
        if (request.ResourcePurpose != ResourcePurpose.Template && request.ResourcePurpose != ResourcePurpose.User)
            return BadRequest($"无效的资源用途: {request.ResourcePurpose}");

        // 模板资源需要管理员权限
        if (request.ResourcePurpose == ResourcePurpose.Template && !User.IsInRole("Admin"))
            return Forbid("只有管理员可以添加模板资源");

        try
        {
            // 获取当前用户ID
            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;

            // 读取文件数据
            using var memoryStream = new MemoryStream();
            await file.CopyToAsync(memoryStream);
            var fileData = memoryStream.ToArray();

            var result = _resourceManager.AddResource(
                user.ID, request.ResourceType, request.ResourcePurpose,
                file.FileName, fileData, request.ExamID);

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

                logger.Error($"添加资源时出错: {result.Error.Message}");
                return StatusCode(StatusCodes.Status500InternalServerError, $"添加资源失败: {result.Error.Message}");
            }

            var resource = result.Value;
            var resourceInfo = new ResourceInfo
            {
                ID = resource.ID.ToString(),
                Name = resource.ResourceName,
                Type = resource.ResourceType,
                Purpose = resource.Purpose,
                UploadTime = resource.UploadTime,
                ExamID = resource.ExamID,
                MimeType = resource.MimeType
            };

            logger.Info($"成功添加资源: {request.ResourceType}/{request.ResourcePurpose}/{file.FileName}");
            return CreatedAtAction(nameof(GetResourceById), new { resourceId = resource.ID }, resourceInfo);
        }
        catch (Exception ex)
        {
            logger.Error($"添加资源 {request.ResourceType}/{request.ResourcePurpose}/{file.FileName} 时出错: {ex.Message}");
            return StatusCode(StatusCodes.Status500InternalServerError, $"添加资源失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 获取资源列表
    /// </summary>
    /// <param name="examId">实验ID（可选）</param>
    /// <param name="resourceType">资源类型（可选）</param>
    /// <param name="resourcePurpose">资源用途（可选）</param>
    /// <returns>资源列表</returns>
    [Authorize]
    [HttpGet]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(ResourceInfo[]), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public IActionResult GetResourceList(
        [FromQuery] string? examId = null,
        [FromQuery] string? resourceType = null,
        [FromQuery] ResourcePurpose? resourcePurpose = null)
    {
        try
        {
            // 获取当前用户ID
            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;

            Result<List<Resource>> result;
            // 管理员
            if (user.Permission == UserPermission.Admin)
            {
                result = _resourceManager.GetFullResourceList(examId, resourceType, resourcePurpose);
            }
            // 用户
            else if (resourcePurpose == ResourcePurpose.User)
            {
                result = _resourceManager.GetFullResourceList(examId, resourceType, resourcePurpose, user.ID);
            }
            // 模板
            else if (resourcePurpose == ResourcePurpose.Template)
            {
                result = _resourceManager.GetFullResourceList(examId, resourceType, resourcePurpose);
            }
            // 其他
            else
            {
                // 这种情况下需要分别查询并合并结果
                var userResourcesResult = _resourceManager.GetFullResourceList(
                    examId, resourceType, ResourcePurpose.User, user.ID);
                var templateResourcesResult = _resourceManager.GetFullResourceList(
                    examId, resourceType, ResourcePurpose.Template, null);

                if (!userResourcesResult.IsSuccessful || !templateResourcesResult.IsSuccessful)
                {
                    logger.Error($"获取资源列表时出错");
                    return StatusCode(StatusCodes.Status500InternalServerError, "获取资源列表失败");
                }

                var allResources = userResourcesResult.Value.Concat(templateResourcesResult.Value)
                    .OrderByDescending(r => r.UploadTime);
                var mergedResourceInfos = allResources.Select(r => new ResourceInfo
                {
                    ID = r.ID.ToString(),
                    Name = r.ResourceName,
                    Type = r.ResourceType,
                    Purpose = r.Purpose,
                    UploadTime = r.UploadTime,
                    ExamID = r.ExamID,
                    MimeType = r.MimeType
                }).ToArray();

                logger.Info($"成功获取资源列表，共 {mergedResourceInfos.Length} 个资源");
                return Ok(mergedResourceInfos);
            }

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

            var resources = result.Value.Select(r => new ResourceInfo
            {
                ID = r.ID.ToString(),
                Name = r.ResourceName,
                Type = r.ResourceType,
                Purpose = r.Purpose,
                UploadTime = r.UploadTime,
                ExamID = r.ExamID,
                MimeType = r.MimeType
            }).ToArray();

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

    /// <summary>
    /// 根据资源ID下载资源
    /// </summary>
    /// <param name="resourceId">资源ID</param>
    /// <returns>资源文件</returns>
    [HttpGet("{resourceId}")]
    [EnableCors("Users")]
    [ProducesResponseType(typeof(FileResult), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public IActionResult GetResourceById(string resourceId)
    {
        try
        {
            var result = _resourceManager.GetResourceById(resourceId);

            if (!result.HasValue)
            {
                logger.Warn($"资源不存在: {resourceId}");
                return NotFound($"资源 {resourceId} 不存在");
            }

            var resource = result.Value;
            logger.Info($"成功获取资源: {resourceId} ({resource.ResourceName})");

            var dataRet = _resourceManager.ReadBytesFromPath(resource.Path);
            if (!dataRet.IsSuccessful)
            {
                logger.Error($"读取资源数据时出错: {dataRet.Error.Message}");
                return StatusCode(StatusCodes.Status500InternalServerError, $"读取资源数据失败: {dataRet.Error.Message}");
            }

            return File(dataRet.Value, resource.MimeType ?? "application/octet-stream", resource.ResourceName);
        }
        catch (Exception ex)
        {
            logger.Error($"获取资源 {resourceId} 时出错: {ex.Message}");
            return StatusCode(StatusCodes.Status500InternalServerError, $"获取资源失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 删除资源
    /// </summary>
    /// <param name="resourceId">资源ID</param>
    /// <returns>删除结果</returns>
    [Authorize]
    [HttpDelete("{resourceId}")]
    [EnableCors("Users")]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status401Unauthorized)]
    [ProducesResponseType(StatusCodes.Status403Forbidden)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public IActionResult DeleteResource(string resourceId)
    {
        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 resourceResult = _resourceManager.GetResourceById(resourceId);

            if (!resourceResult.HasValue)
            {
                logger.Warn($"资源不存在: {resourceId}");
                return NotFound($"资源 {resourceId} 不存在");
            }

            var resource = resourceResult.Value;

            // 权限检查：管理员可以删除所有资源，普通用户只能删除自己的用户资源
            if (!User.IsInRole("Admin"))
            {
                if (resource.Purpose == ResourcePurpose.Template)
                    return Forbid("普通用户不能删除模板资源");

                if (resource.UserID != user.ID)
                    return Forbid("只能删除自己的资源");
            }

            var deleteResult = _resourceManager.DeleteResource(resourceId);
            if (!deleteResult.IsSuccessful)
            {
                logger.Error($"删除资源时出错: {deleteResult.Error.Message}");
                return StatusCode(StatusCodes.Status500InternalServerError, $"删除资源失败: {deleteResult.Error.Message}");
            }

            logger.Info($"成功删除资源: {resourceId} ({resource.ResourceName})");
            return NoContent();
        }
        catch (Exception ex)
        {
            logger.Error($"删除资源 {resourceId} 时出错: {ex.Message}");
            return StatusCode(StatusCodes.Status500InternalServerError, $"删除资源失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 资源信息类
    /// </summary>
    public class ResourceInfo
    {
        /// <summary>
        /// 资源ID
        /// </summary>
        public required string ID { get; set; }

        /// <summary>
        /// 资源名称
        /// </summary>
        public required string Name { get; set; }

        /// <summary>
        /// 资源类型
        /// </summary>
        public required string Type { get; set; }

        /// <summary>
        /// 资源用途（template/user）
        /// </summary>
        public required ResourcePurpose Purpose { get; set; }

        /// <summary>
        /// 上传时间
        /// </summary>
        public DateTime UploadTime { get; set; }

        /// <summary>
        /// 所属实验ID（可选）
        /// </summary>
        public string? ExamID { get; set; }

        /// <summary>
        /// MIME类型
        /// </summary>
        public string? MimeType { get; set; }
    }

    /// <summary>
    /// 添加资源请求类
    /// </summary>
    public class AddResourceRequest
    {
        /// <summary>
        /// 资源类型
        /// </summary>
        public required string ResourceType { get; set; }

        /// <summary>
        /// 资源用途（template/user）
        /// </summary>
        public required ResourcePurpose ResourcePurpose { get; set; }

        /// <summary>
        /// 所属实验ID（可选）
        /// </summary>
        public string? ExamID { get; set; }
    }

}
