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

namespace Meezi.API.Controllers;

[Route("api/cafes/{cafeId}/reviews")]
public class CafeReviewsController : CafeApiControllerBase
{
    private readonly IReviewService _reviews;
    private readonly IValidator<ReplyCafeReviewRequest> _replyValidator;

    public CafeReviewsController(IReviewService reviews, IValidator<ReplyCafeReviewRequest> replyValidator)
    {
        _reviews = reviews;
        _replyValidator = replyValidator;
    }

    [HttpGet]
    public async Task<IActionResult> List(
        string cafeId,
        ITenantContext tenant,
        CancellationToken ct,
        [FromQuery] int page = 1,
        [FromQuery] int pageSize = 20)
    {
        if (EnsureCafeAccess(cafeId, tenant) is { } denied) return denied;
        var data = await _reviews.GetReviewsAsync(cafeId, page, pageSize, publicOnly: false, ct);
        return Ok(new ApiResponse<IReadOnlyList<CafeReviewDto>>(true, data));
    }

    [HttpPatch("{reviewId}/reply")]
    public async Task<IActionResult> Reply(
        string cafeId,
        string reviewId,
        [FromBody] ReplyCafeReviewRequest request,
        ITenantContext tenant,
        CancellationToken ct = default)
    {
        if (EnsureCafeAccess(cafeId, tenant) is { } denied) return denied;
        var validation = await _replyValidator.ValidateAsync(request, ct);
        if (!validation.IsValid)
        {
            var first = validation.Errors.First();
            return BadRequest(new ApiResponse<object>(false, null, new ApiError("VALIDATION_ERROR", first.ErrorMessage, first.PropertyName)));
        }

        var data = await _reviews.ReplyReviewAsync(cafeId, reviewId, request.Reply, ct);
        if (data is null) return NotFoundError();
        return Ok(new ApiResponse<CafeReviewDto>(true, data));
    }

    [HttpPatch("{reviewId}/visibility")]
    public async Task<IActionResult> SetVisibility(
        string cafeId,
        string reviewId,
        [FromBody] HideCafeReviewRequest request,
        ITenantContext tenant,
        CancellationToken ct = default)
    {
        if (EnsureCafeAccess(cafeId, tenant) is { } denied) return denied;
        var data = await _reviews.SetHiddenAsync(cafeId, reviewId, request.IsHidden, ct);
        if (data is null) return NotFoundError();
        return Ok(new ApiResponse<CafeReviewDto>(true, data));
    }
}
