// EN: Controller for table management.
// VI: Controller quản lý bàn.

using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using FnbEngine.API.Application.Commands;
using FnbEngine.API.Application.Queries;
using FnbEngine.Domain.AggregatesModel.TableAggregate;

namespace FnbEngine.API.Controllers;

/// <summary>
/// EN: Controller for table management.
/// VI: Controller quản lý bàn.
/// </summary>
[ApiController]
[Route("api/v1/tables")]
[Authorize]
public class TablesController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly ILogger<TablesController> _logger;
    private readonly ITableRepository _tableRepository;

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

    /// <summary>
    /// EN: Get tables by shop ID.
    /// VI: Lấy danh sách bàn theo shop ID.
    /// </summary>
    [HttpGet]
    [ProducesResponseType(typeof(ApiResponse<IEnumerable<TableDto>>), 200)]
    public async Task<ActionResult<ApiResponse<IEnumerable<TableDto>>>> GetTables(
        [FromQuery] Guid shopId,
        CancellationToken ct = default)
    {
        var result = await _mediator.Send(new GetTablesQuery(shopId), ct);
        return Ok(new ApiResponse<IEnumerable<TableDto>> { Success = true, Data = result });
    }

    /// <summary>
    /// EN: Create a new table.
    /// VI: Tạo bàn mới.
    /// </summary>
    [HttpPost]
    [ProducesResponseType(typeof(ApiResponse<CreateTableResult>), 201)]
    [ProducesResponseType(400)]
    public async Task<ActionResult<ApiResponse<CreateTableResult>>> CreateTable(
        [FromBody] CreateTableRequest request,
        CancellationToken ct = default)
    {
        var command = new CreateTableCommand(
            request.ShopId,
            request.TableNumber,
            request.Capacity,
            request.Zone,
            request.HourlyRate);

        var result = await _mediator.Send(command, ct);
        return CreatedAtAction(nameof(GetTables), new { shopId = request.ShopId },
            new ApiResponse<CreateTableResult> { Success = true, Data = result });
    }

    /// <summary>
    /// EN: Update table details.
    /// VI: Cập nhật thông tin bàn.
    /// </summary>
    [HttpPut("{id}")]
    [ProducesResponseType(typeof(ApiResponse<bool>), 200)]
    [ProducesResponseType(404)]
    public async Task<ActionResult<ApiResponse<bool>>> UpdateTable(
        Guid id,
        [FromBody] UpdateTableRequest request,
        CancellationToken ct = default)
    {
        var command = new UpdateTableCommand(
            id,
            request.Capacity,
            request.Zone,
            request.PositionX,
            request.PositionY,
            request.HourlyRate);

        var result = await _mediator.Send(command, ct);
        return Ok(new ApiResponse<bool> { Success = true, Data = result });
    }

    /// <summary>
    /// EN: Change table status.
    /// VI: Đổi trạng thái bàn.
    /// </summary>
    [HttpPatch("{id}/status")]
    [ProducesResponseType(typeof(ApiResponse<bool>), 200)]
    [ProducesResponseType(404)]
    public async Task<ActionResult<ApiResponse<bool>>> ChangeStatus(
        Guid id,
        [FromBody] ChangeStatusRequest request,
        CancellationToken ct = default)
    {
        var command = new ChangeTableStatusCommand(id, request.Status);
        var result = await _mediator.Send(command, ct);
        return Ok(new ApiResponse<bool> { Success = true, Data = result });
    }
    /// <summary>
    /// EN: Generate QR token for a table.
    /// VI: Tạo QR token cho bàn.
    /// </summary>
    [HttpPost("{id}/generate-qr")]
    [ProducesResponseType(typeof(ApiResponse<object>), 200)]
    [ProducesResponseType(404)]
    public async Task<ActionResult<ApiResponse<object>>> GenerateQrToken(
        Guid id,
        CancellationToken ct = default)
    {
        var table = await _tableRepository.GetByIdAsync(id, ct);
        if (table is null)
            return NotFound(new ApiResponse<object> { Success = false, Error = "Table not found" });

        var token = table.GenerateQrToken();
        _tableRepository.Update(table);
        await _tableRepository.UnitOfWork.SaveEntitiesAsync(ct);

        return Ok(new ApiResponse<object> { Success = true, Data = new { qrToken = token } });
    }

    /// <summary>
    /// EN: Get table by QR token (public, no auth).
    /// VI: Lấy bàn theo QR token (public, không cần auth).
    /// </summary>
    [AllowAnonymous]
    [HttpGet("by-token/{token}")]
    [ProducesResponseType(typeof(ApiResponse<object>), 200)]
    [ProducesResponseType(404)]
    public async Task<ActionResult<ApiResponse<object>>> GetByQrToken(
        string token,
        CancellationToken ct = default)
    {
        var table = await _tableRepository.GetByQrTokenAsync(token, ct);
        if (table is null)
            return NotFound(new ApiResponse<object> { Success = false, Error = "Table not found" });

        return Ok(new ApiResponse<object>
        {
            Success = true,
            Data = new { table.Id, table.ShopId, table.TableNumber, table.Capacity, table.Zone }
        });
    }
}

/// <summary>
/// EN: Request to create a table.
/// VI: Request tạo bàn.
/// </summary>
public record CreateTableRequest(
    Guid ShopId,
    string TableNumber,
    int Capacity,
    string? Zone = null,
    decimal? HourlyRate = null);

/// <summary>
/// EN: Request to update table details.
/// VI: Request cập nhật thông tin bàn.
/// </summary>
public record UpdateTableRequest(
    int? Capacity = null,
    string? Zone = null,
    int? PositionX = null,
    int? PositionY = null,
    decimal? HourlyRate = null);

/// <summary>
/// EN: Request to change table status.
/// VI: Request đổi trạng thái bàn.
/// </summary>
public record ChangeStatusRequest(string Status);

/// <summary>
/// EN: Standard API response wrapper.
/// VI: Wrapper response API chuẩn.
/// </summary>
public class ApiResponse<T>
{
    public bool Success { get; set; }
    public T? Data { get; set; }
    public string? Error { get; set; }
}
