namespace WalletService.API.Controllers;

using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;
using WalletService.API.Application.Commands;
using WalletService.API.Application.Queries;

/// <summary>
/// EN: Controller for points management operations
/// VI: Controller cho các thao tác quản lý điểm
/// </summary>
[ApiController]
[Route("api/v1/[controller]")]
[Authorize]
[SwaggerTag("Points management endpoints / Các endpoint quản lý điểm")]
public class PointsController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly ILogger<PointsController> _logger;

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

    /// <summary>
    /// EN: Get point account by user ID
    /// VI: Lấy tài khoản điểm theo user ID
    /// </summary>
    [HttpGet("{userId:guid}")]
    [SwaggerOperation(Summary = "Get point account", Description = "Get point account by user ID")]
    [SwaggerResponse(200, "Success", typeof(ApiResponse<PointAccountDto>))]
    [SwaggerResponse(404, "Point account not found")]
    public async Task<IActionResult> GetPointAccount(Guid userId)
    {
        var result = await _mediator.Send(new GetPointAccountQuery(userId));

        if (result == null)
            return NotFound(new ApiResponse<object>(false, "Point account not found"));

        return Ok(new ApiResponse<PointAccountDto>(true, "Success", result));
    }

    /// <summary>
    /// EN: Create a new point account
    /// VI: Tạo tài khoản điểm mới
    /// </summary>
    [HttpPost]
    [SwaggerOperation(Summary = "Create point account", Description = "Create a new point account for a user")]
    [SwaggerResponse(201, "Point account created", typeof(ApiResponse<CreatePointAccountResult>))]
    [SwaggerResponse(409, "Point account already exists")]
    public async Task<IActionResult> CreatePointAccount([FromBody] CreatePointAccountRequest request)
    {
        var command = new CreatePointAccountCommand(request.UserId);
        var result = await _mediator.Send(command);

        return CreatedAtAction(
            nameof(GetPointAccount),
            new { userId = result.UserId },
            new ApiResponse<CreatePointAccountResult>(true, "Point account created", result));
    }

    /// <summary>
    /// EN: Earn points
    /// VI: Tích điểm
    /// </summary>
    [HttpPost("{userId:guid}/earn")]
    [SwaggerOperation(Summary = "Earn points", Description = "Add points to user account")]
    [SwaggerResponse(200, "Points earned", typeof(ApiResponse<PointTransactionResult>))]
    [SwaggerResponse(400, "Invalid request")]
    [SwaggerResponse(404, "Point account not found")]
    public async Task<IActionResult> EarnPoints(Guid userId, [FromBody] EarnPointsRequest request)
    {
        var command = new EarnPointsCommand(
            userId,
            request.Points,
            request.Source,
            request.Description,
            request.ExpiryMonths);

        var result = await _mediator.Send(command);

        return Ok(new ApiResponse<PointTransactionResult>(true, "Points earned", result));
    }

    /// <summary>
    /// EN: Spend points
    /// VI: Tiêu điểm
    /// </summary>
    [HttpPost("{userId:guid}/spend")]
    [SwaggerOperation(Summary = "Spend points", Description = "Spend points from user account")]
    [SwaggerResponse(200, "Points spent", typeof(ApiResponse<PointTransactionResult>))]
    [SwaggerResponse(400, "Insufficient points")]
    [SwaggerResponse(404, "Point account not found")]
    public async Task<IActionResult> SpendPoints(Guid userId, [FromBody] SpendPointsRequest request)
    {
        var command = new SpendPointsCommand(userId, request.Points, request.Source, request.Description);
        var result = await _mediator.Send(command);

        return Ok(new ApiResponse<PointTransactionResult>(true, "Points spent", result));
    }

    /// <summary>
    /// EN: Get point transactions
    /// VI: Lấy lịch sử giao dịch điểm
    /// </summary>
    [HttpGet("{userId:guid}/transactions")]
    [SwaggerOperation(Summary = "Get point transactions", Description = "Get point transaction history")]
    [SwaggerResponse(200, "Success", typeof(ApiResponse<PointTransactionsDto>))]
    [SwaggerResponse(404, "Point account not found")]
    public async Task<IActionResult> GetTransactions(
        Guid userId,
        [FromQuery] int page = 1,
        [FromQuery] int pageSize = 20)
    {
        var query = new GetPointTransactionsQuery(userId, page, pageSize);
        var result = await _mediator.Send(query);

        return Ok(new ApiResponse<PointTransactionsDto>(true, "Success", result));
    }
}

#region Request DTOs

public record CreatePointAccountRequest(Guid UserId);
public record EarnPointsRequest(long Points, string Source, string Description, int? ExpiryMonths = 12);
public record SpendPointsRequest(long Points, string Source, string Description);

#endregion
