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

namespace Meezi.API.Controllers;

[Route("api/cafes/{cafeId}/branches/{branchId}/menu")]
public class BranchMenuController : CafeApiControllerBase
{
    private readonly IBranchMenuService _branchMenu;
    private readonly IValidator<UpsertBranchMenuOverrideRequest> _upsertValidator;

    public BranchMenuController(
        IBranchMenuService branchMenu,
        IValidator<UpsertBranchMenuOverrideRequest> upsertValidator)
    {
        _branchMenu = branchMenu;
        _upsertValidator = upsertValidator;
    }

    [HttpGet]
    public async Task<IActionResult> GetBranchMenu(
        string cafeId,
        string branchId,
        ITenantContext tenant,
        CancellationToken cancellationToken,
        [FromQuery] bool includeUnavailable = false)
    {
        if (EnsureCafeAccess(cafeId, tenant) is { } denied) return denied;

        var data = await _branchMenu.GetBranchMenuAsync(
            cafeId, branchId, includeUnavailable, cancellationToken);
        if (data is null)
            return NotFound(new ApiResponse<object>(
                false, null, new ApiError("BRANCH_NOT_FOUND", "Branch not found.")));

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

    [HttpPut("{menuItemId}/override")]
    [Authorize(Roles = "Manager,Owner")]
    public async Task<IActionResult> UpsertOverride(
        string cafeId,
        string branchId,
        string menuItemId,
        [FromBody] UpsertBranchMenuOverrideRequest request,
        ITenantContext tenant,
        CancellationToken cancellationToken = default)
    {
        if (EnsureCafeAccess(cafeId, tenant) is { } denied) return denied;
        if (!BranchMenuService.CanManageOverrides(tenant.Role))
            return Forbid();

        var validation = await _upsertValidator.ValidateAsync(request, cancellationToken);
        if (!validation.IsValid) return BadRequest(ValidationError(validation));

        var plan = tenant.PlanTier ?? PlanTier.Free;
        var result = await _branchMenu.UpsertOverrideAsync(
            cafeId,
            branchId,
            menuItemId,
            request,
            plan,
            tenant.Role,
            tenant.UserId,
            cancellationToken);

        if (!result.Success)
        {
            var status = result.ErrorCode == "PLAN_LIMIT_REACHED"
                ? StatusCodes.Status403Forbidden
                : StatusCodes.Status400BadRequest;
            return StatusCode(status,
                new ApiResponse<object>(false, null,
                    new ApiError(result.ErrorCode!, result.Message!)));
        }

        return Ok(new ApiResponse<BranchMenuOverrideDto>(true, result.Data));
    }

    [HttpDelete("{menuItemId}/override")]
    [Authorize(Roles = "Owner")]
    public async Task<IActionResult> DeleteOverride(
        string cafeId,
        string branchId,
        string menuItemId,
        ITenantContext tenant,
        CancellationToken cancellationToken = default)
    {
        if (EnsureCafeAccess(cafeId, tenant) is { } denied) return denied;

        var deleted = await _branchMenu.DeleteOverrideAsync(
            cafeId, branchId, menuItemId, cancellationToken);
        if (!deleted)
            return NotFoundError("Override not found.");

        return Ok(new ApiResponse<object>(true, new { menuItemId }));
    }
}
