using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using StorageService.API.Application.Commands.Admin;
using StorageService.API.Application.Queries.Admin;
using Swashbuckle.AspNetCore.Annotations;
using System.Security.Claims;
using Asp.Versioning;

namespace StorageService.API.Controllers.Admin;

/// <summary>
/// EN: Admin controller for quota management.
/// VI: Controller admin cho quản lý quota.
/// </summary>
[ApiController]
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/admin/quotas")]
[Authorize(Roles = "Admin,SuperAdmin")]
[SwaggerTag("Admin Quota Management - View and manage user storage quotas")]
public class AdminQuotaController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly ILogger<AdminQuotaController> _logger;

    public AdminQuotaController(IMediator mediator, ILogger<AdminQuotaController> logger)
    {
        _mediator = mediator;
        _logger = logger;
    }

    /// <summary>
    /// EN: Get all users' quotas with pagination.
    /// VI: Lấy quota của tất cả users với phân trang.
    /// </summary>
    [HttpGet]
    [SwaggerOperation(Summary = "Get all quotas", Description = "Get all users' storage quotas with pagination and filtering")]
    [SwaggerResponse(200, "Quotas retrieved successfully")]
    [SwaggerResponse(403, "Forbidden - Admin role required")]
    public async Task<ActionResult<ApiResponse<AllUsersQuotaResult>>> GetAll(
        [FromQuery] int pageNumber = 1,
        [FromQuery] int pageSize = 20,
        [FromQuery] string? quotaTier = null,
        [FromQuery] double? minUsagePercentage = null,
        [FromQuery] string? sortBy = null,
        [FromQuery] bool descending = false,
        CancellationToken cancellationToken = default)
    {
        var query = new GetAllUsersQuotaQuery(pageNumber, pageSize, quotaTier, minUsagePercentage, sortBy, descending);
        var result = await _mediator.Send(query, cancellationToken);

        return Ok(new ApiResponse<AllUsersQuotaResult> { Success = true, Data = result });
    }

    /// <summary>
    /// EN: Get quota by user ID.
    /// VI: Lấy quota theo user ID.
    /// </summary>
    [HttpGet("{userId}")]
    [SwaggerOperation(Summary = "Get user quota", Description = "Get storage quota for a specific user")]
    [SwaggerResponse(200, "Quota retrieved successfully")]
    [SwaggerResponse(404, "User quota not found")]
    public async Task<ActionResult<ApiResponse<AdminQuotaDto>>> GetByUserId(
        string userId,
        CancellationToken cancellationToken = default)
    {
        var query = new GetAllUsersQuotaQuery(1, 1);
        var result = await _mediator.Send(query, cancellationToken);
        
        var quota = result.Items.FirstOrDefault(q => q.UserId == userId);
        if (quota == null)
            return NotFound(new ApiResponse<AdminQuotaDto> { Success = false, Error = "Quota not found for user" });

        return Ok(new ApiResponse<AdminQuotaDto> { Success = true, Data = quota });
    }

    /// <summary>
    /// EN: Update user quota limits.
    /// VI: Cập nhật giới hạn quota của user.
    /// </summary>
    [HttpPut("{userId}")]
    [SwaggerOperation(Summary = "Update user quota", Description = "Update storage quota limits for a user")]
    [SwaggerResponse(200, "Quota updated successfully")]
    [SwaggerResponse(400, "Invalid request or business rule violation")]
    public async Task<ActionResult<ApiResponse<QuotaUpdatedDto>>> Update(
        string userId,
        [FromBody] UpdateQuotaRequest request,
        CancellationToken cancellationToken = default)
    {
        var adminUserId = GetUserId();
        _logger.LogInformation("Admin {AdminId} updating quota for user {UserId}", adminUserId, userId);

        var command = new UpdateUserQuotaCommand(userId, request.MaxStorageBytes, request.MaxFileCount, request.QuotaTier);
        var result = await _mediator.Send(command, cancellationToken);

        if (!result.Success)
            return BadRequest(new ApiResponse<QuotaUpdatedDto> { Success = false, Error = result.Error });

        return Ok(new ApiResponse<QuotaUpdatedDto> { Success = true, Data = result.Data });
    }

    private string? GetUserId() => User.FindFirstValue(ClaimTypes.NameIdentifier);
}

/// <summary>
/// EN: Request model for updating user quota.
/// VI: Request model để cập nhật quota user.
/// </summary>
public record UpdateQuotaRequest(
    long MaxStorageBytes,
    int MaxFileCount,
    string? QuotaTier = null);
