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

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

namespace CatalogService.API.Controllers;

/// <summary>
/// EN: Products API Controller.
/// VI: Controller API Products.
/// </summary>
[ApiController]
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/products")]
[Authorize]
public class ProductsController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly ILogger<ProductsController> _logger;

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

    /// <summary>
    /// EN: Get products by shop with filtering and pagination.
    /// VI: Lấy sản phẩm theo shop có lọc và phân trang.
    /// </summary>
    [HttpGet]
    [ProducesResponseType(typeof(PagedResult<ProductDto>), StatusCodes.Status200OK)]
    public async Task<ActionResult<PagedResult<ProductDto>>> GetProducts(
        [FromQuery] Guid shopId,
        [FromQuery] bool? isActive = null,
        [FromQuery] string? type = null,
        [FromQuery] Guid? categoryId = null,
        [FromQuery] int page = 1,
        [FromQuery] int pageSize = 20,
        CancellationToken cancellationToken = default)
    {
        var query = new GetProductsQuery
        {
            ShopId = shopId,
            IsActive = isActive,
            Type = type,
            CategoryId = categoryId,
            Page = page,
            PageSize = pageSize
        };

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

    /// <summary>
    /// EN: Get products for a specific shop (RESTful path).
    /// VI: Lấy sản phẩm của một shop cụ thể (đường dẫn RESTful).
    /// </summary>
    [HttpGet("~/api/v{version:apiVersion}/shops/{shopId}/products")]
    [ProducesResponseType(typeof(PagedResult<ProductDto>), StatusCodes.Status200OK)]
    public async Task<ActionResult<PagedResult<ProductDto>>> GetShopProducts(
        Guid shopId,
        [FromQuery] bool? isActive = null,
        [FromQuery] string? type = null,
        [FromQuery] Guid? categoryId = null,
        [FromQuery] int page = 1,
        [FromQuery] int pageSize = 20,
        CancellationToken cancellationToken = default)
    {
        var query = new GetProductsQuery
        {
            ShopId = shopId,
            IsActive = isActive,
            Type = type,
            CategoryId = categoryId,
            Page = page,
            PageSize = pageSize
        };

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

    /// <summary>
    /// EN: Lookup product by barcode or SKU (for POS scanner).
    /// VI: Tra cứu sản phẩm theo barcode hoặc SKU (cho máy quét POS).
    /// </summary>
    [HttpGet("lookup")]
    [ProducesResponseType(typeof(ProductDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<ProductDto>> LookupProduct(
        [FromQuery] Guid shopId,
        [FromQuery] string barcode,
        CancellationToken cancellationToken = default)
    {
        if (shopId == Guid.Empty || string.IsNullOrWhiteSpace(barcode))
        {
            return BadRequest(new { success = false, error = new { code = "INVALID_REQUEST", message = "Shop ID and barcode are required / Shop ID và barcode là bắt buộc" } });
        }

        var query = new GetProductByBarcodeQuery(shopId, barcode.Trim());
        var result = await _mediator.Send(query, cancellationToken);

        if (result == null)
        {
            return NotFound(new { success = false, error = new { code = "PRODUCT_NOT_FOUND", message = $"No product found for barcode/SKU '{barcode}' / Không tìm thấy sản phẩm cho barcode/SKU '{barcode}'" } });
        }

        return Ok(new { success = true, data = result });
    }

    /// <summary>
    /// EN: Get product by ID.
    /// VI: Lấy sản phẩm theo ID.
    /// </summary>
    [HttpGet("{id}")]
    [ProducesResponseType(typeof(ProductDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<ProductDto>> GetProduct(
        Guid id,
        CancellationToken cancellationToken = default)
    {
        var query = new GetProductByIdQuery(id);
        var result = await _mediator.Send(query, cancellationToken);

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

        return Ok(result);
    }

    /// <summary>
    /// EN: Create a new product.
    /// VI: Tạo sản phẩm mới.Catalog
    /// </summary>
    [HttpPost]
    [ProducesResponseType(typeof(Guid), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<ActionResult<Guid>> CreateProduct(
        [FromBody] CreateProductCommand command,
        CancellationToken cancellationToken = default)
    {
        var productId = await _mediator.Send(command, cancellationToken);
        return CreatedAtAction(
            nameof(GetProduct),
            new { id = productId },
            productId);
    }

    /// <summary>
    /// EN: Update an existing product.
    /// VI: Cập nhật sản phẩm hiện tại.
    /// </summary>
    [HttpPut("{id}")]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> UpdateProduct(
        Guid id,
        [FromBody] UpdateProductCommand command,
        CancellationToken cancellationToken = default)
    {
        // EN: Ensure ID in route matches command
        // VI: Đảm bảo ID trong route khớp với command
        if (id != command.ProductId)
        {
            return BadRequest(new { Message = "Product ID mismatch" });
        }

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

    /// <summary>
    /// EN: Delete (deactivate) a product.
    /// VI: Xóa (vô hiệu hóa) sản phẩm.
    /// </summary>
    [HttpDelete("{id}")]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> DeleteProduct(
        Guid id,
        CancellationToken cancellationToken = default)
    {
        var command = new DeleteProductCommand(id);
        await _mediator.Send(command, cancellationToken);
        return NoContent();
    }
}
