using FluentValidation;
using Microsoft.AspNetCore.Mvc;
using Meezi.API.Models.Public;
using Meezi.API.Services;
using Meezi.Core.Authorization;
using Meezi.Core.Enums;
using Meezi.Core.Interfaces;
using Meezi.Infrastructure.Services.Platform;
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;
    private readonly IPlatformCatalogService _catalog;

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

    [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;
        if (EnsurePermission(tenant, Permission.ManageReviews) is { } permDenied) return permDenied;

        // Replying to reviews is a paid feature (Starter+).
        var tier = tenant.PlanTier ?? PlanTier.Free;
        if (!await _catalog.IsFeatureEnabledForCafeAsync(cafeId, tier, "review_reply", ct))
            return StatusCode(403, new ApiResponse<object>(false, null,
                new ApiError("PLAN_FEATURE_DISABLED", "Replying to reviews is not included in your plan. Please upgrade.")));

        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;
        if (EnsurePermission(tenant, Permission.ManageReviews) is { } permDenied) return permDenied;
        var data = await _reviews.SetHiddenAsync(cafeId, reviewId, request.IsHidden, ct);
        if (data is null) return NotFoundError();
        return Ok(new ApiResponse<CafeReviewDto>(true, data));
    }
}
