// EN: Orders REST API Controller.
// VI: Controller REST API cho Orders.

using Asp.Versioning;
using MediatR;
using Microsoft.AspNetCore.Mvc;
using OrderService.API.Application.Commands;
using OrderService.API.Application.DTOs;
using OrderService.API.Application.Queries;

namespace OrderService.API.Controllers;

/// <summary>
/// EN: Orders API Controller for order management.
/// VI: Controller API Orders cho quản lý đơn hàng.
/// </summary>
[ApiController]
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/orders")]
public class OrdersController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly ILogger<OrdersController> _logger;

    public OrdersController(
        IMediator mediator,
        ILogger<OrdersController> logger)
    {
        _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    /// <summary>
    /// EN: Create a new order.
    /// VI: Tạo order mới.
    /// </summary>
    [HttpPost]
    [ProducesResponseType(typeof(CreateOrderResult), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<ActionResult<CreateOrderResult>> CreateOrder(
        [FromBody] CreateOrderCommand command,
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Creating order for shop {ShopId} / VI: Tạo order cho shop {ShopId}",
            command.ShopId);

        var result = await _mediator.Send(command, cancellationToken);

        return CreatedAtAction(
            nameof(GetOrderById),
            new { id = result.OrderId },
            result);
    }

    /// <summary>
    /// EN: Get order by ID.
    /// VI: Lấy order theo ID.
    /// </summary>
    [HttpGet("{id}")]
    [ProducesResponseType(typeof(OrderDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<OrderDto>> GetOrderById(
        Guid id,
        [FromQuery] Guid shopId,
        CancellationToken cancellationToken = default)
    {
        var query = new GetOrderByIdQuery(id, shopId);
        var result = await _mediator.Send(query, cancellationToken);

        if (result == null)
        {
            return NotFound(new { Message = $"Order with ID {id} not found" });
        }

        return Ok(result);
    }

    /// <summary>
    /// EN: List orders by shop with filtering and pagination.
    /// VI: Liệt kê orders theo shop có lọc và phân trang.
    /// </summary>
    [HttpGet]
    [ProducesResponseType(typeof(PagedResult<OrderSummaryDto>), StatusCodes.Status200OK)]
    public async Task<ActionResult<PagedResult<OrderSummaryDto>>> ListOrdersByShop(
        [FromQuery] Guid shopId,
        [FromQuery] string? status = null,
        [FromQuery] DateTime? fromDate = null,
        [FromQuery] DateTime? toDate = null,
        [FromQuery] int page = 1,
        [FromQuery] int pageSize = 20,
        CancellationToken cancellationToken = default)
    {
        var query = new ListOrdersByShopQuery(
            shopId,
            status,
            fromDate,
            toDate,
            page,
            pageSize);

        var result = await _mediator.Send(query, cancellationToken);
        return Ok(result);
    }

    /// <summary>
    /// EN: Process payment for an order.
    /// VI: Xử lý thanh toán cho order.
    /// </summary>
    [HttpPost("{id}/pay")]
    [ProducesResponseType(typeof(PayOrderResult), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<PayOrderResult>> PayOrder(
        Guid id,
        [FromQuery] Guid shopId,
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Processing payment for order {OrderId} / VI: Xử lý thanh toán cho order {OrderId}",
            id);

        var command = new PayOrderCommand(id, shopId);
        var result = await _mediator.Send(command, cancellationToken);

        return Ok(result);
    }

    /// <summary>
    /// EN: Cancel an order.
    /// VI: Hủy order.
    /// </summary>
    [HttpPost("{id}/cancel")]
    [ProducesResponseType(typeof(CancelOrderResult), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CancelOrderResult>> CancelOrder(
        Guid id,
        [FromQuery] Guid shopId,
        [FromBody] CancelOrderRequest request,
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Cancelling order {OrderId} / VI: Hủy order {OrderId}",
            id);

        var command = new CancelOrderCommand(id, shopId, request.Reason);
        var result = await _mediator.Send(command, cancellationToken);

        return Ok(result);
    }

    /// <summary>
    /// EN: Complete an order.
    /// VI: Hoàn thành order.
    /// </summary>
    [HttpPost("{id}/complete")]
    [ProducesResponseType(typeof(CompleteOrderResult), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CompleteOrderResult>> CompleteOrder(
        Guid id,
        [FromQuery] Guid shopId,
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Completing order {OrderId} / VI: Hoàn thành order {OrderId}",
            id);

        var command = new CompleteOrderCommand(id, shopId);
        var result = await _mediator.Send(command, cancellationToken);

        return Ok(result);
    }

    /// <summary>
    /// EN: Get orders by customer.
    /// VI: Lấy orders theo khách hàng.
    /// </summary>
    [HttpGet("customer/{customerId}")]
    [ProducesResponseType(typeof(PagedResult<OrderSummaryDto>), StatusCodes.Status200OK)]
    public async Task<ActionResult<PagedResult<OrderSummaryDto>>> GetOrdersByCustomer(
        Guid customerId,
        [FromQuery] int page = 1,
        [FromQuery] int pageSize = 20,
        CancellationToken cancellationToken = default)
    {
        var query = new GetOrdersByCustomerQuery(customerId, page, pageSize);
        var result = await _mediator.Send(query, cancellationToken);

        return Ok(result);
    }
}

/// <summary>
/// EN: Request to cancel an order.
/// VI: Yêu cầu hủy order.
/// </summary>
public record CancelOrderRequest(string Reason);
