using FluentValidation;
using Microsoft.AspNetCore.Mvc;
using Meezi.API.Models.Public;
using Meezi.API.Services;
using Meezi.Core.Enums;
using Meezi.Core.Interfaces;
using Meezi.Shared;

namespace Meezi.API.Controllers;

[Route("api/cafes/{cafeId}/reservations")]
public class ReservationsController : CafeApiControllerBase
{
    private readonly IReservationService _reservations;
    private readonly IValidator<CreateReservationRequest> _createValidator;

    public ReservationsController(
        IReservationService reservations,
        IValidator<CreateReservationRequest> createValidator)
    {
        _reservations = reservations;
        _createValidator = createValidator;
    }

    [HttpPost]
    public async Task<IActionResult> Create(
        string cafeId,
        [FromBody] CreateReservationRequest request,
        ITenantContext tenant,
        CancellationToken ct)
    {
        if (EnsureCafeAccess(cafeId, tenant) is { } denied) return denied;
        var validation = await _createValidator.ValidateAsync(request, ct);
        if (!validation.IsValid) return BadRequest(ValidationError(validation));

        var data = await _reservations.CreateAsync(cafeId, request, ct);
        if (data is null)
            return BadRequest(new ApiResponse<object>(false, null, new ApiError("INVALID_TABLE", "Table not found.")));

        return Ok(new ApiResponse<ReservationDto>(true, data));
    }

    [HttpGet]
    public async Task<IActionResult> List(
        string cafeId,
        ITenantContext tenant,
        [FromQuery] DateOnly? date,
        [FromQuery] ReservationStatus? status,
        CancellationToken ct)
    {
        if (EnsureCafeAccess(cafeId, tenant) is { } denied) return denied;
        var data = await _reservations.GetReservationsAsync(cafeId, date, status, ct);
        return Ok(new ApiResponse<IReadOnlyList<ReservationDto>>(true, data));
    }

    [HttpPatch("{id}/status")]
    public async Task<IActionResult> UpdateStatus(
        string cafeId,
        string id,
        [FromBody] UpdateReservationStatusRequest request,
        ITenantContext tenant,
        CancellationToken ct)
    {
        if (EnsureCafeAccess(cafeId, tenant) is { } denied) return denied;
        var data = await _reservations.UpdateStatusAsync(cafeId, id, request.Status, ct);
        if (data is null) return NotFoundError();
        return Ok(new ApiResponse<ReservationDto>(true, data));
    }
}

public record UpdateReservationStatusRequest(ReservationStatus Status);
