// EN: Admin controller for shop management (Backoffice).
// VI: Controller Admin cho quản lý shop (Backoffice).

using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MerchantService.API.Application.Queries.Admin;
using MerchantService.Domain.AggregatesModel.ShopAggregate;
using MerchantService.Domain.Exceptions;

namespace MerchantService.API.Controllers.Admin;

/// <summary>
/// EN: Admin controller for shop management operations (Backoffice).
/// VI: Controller Admin cho các thao tác quản lý shop (Backoffice).
/// </summary>
[ApiController]
[Route("api/v1/admin/shops")]
[Authorize(Roles = "Admin,SuperAdmin")]
public class AdminShopsController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly IShopRepository _shopRepository;
    private readonly ILogger<AdminShopsController> _logger;

    public AdminShopsController(
        IMediator mediator,
        IShopRepository shopRepository,
        ILogger<AdminShopsController> logger)
    {
        _mediator = mediator;
        _shopRepository = shopRepository;
        _logger = logger;
    }

    /// <summary>
    /// EN: Get all shops with pagination.
    /// VI: Lấy tất cả shops với phân trang.
    /// </summary>
    [HttpGet]
    [ProducesResponseType(typeof(AdminShopListResultDto), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetAllShops(
        [FromQuery] int page = 1,
        [FromQuery] int pageSize = 20,
        [FromQuery] string? status = null,
        [FromQuery] Guid? merchantId = null,
        [FromQuery] string? search = null)
    {
        var query = new GetAllShopsQuery(page, pageSize, status, merchantId, search);
        var result = await _mediator.Send(query);
        return Ok(result);
    }

    /// <summary>
    /// EN: Get shop details by ID.
    /// VI: Lấy chi tiết shop theo ID.
    /// </summary>
    [HttpGet("{shopId:guid}")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> GetShopById(Guid shopId)
    {
        var shop = await _shopRepository.GetByIdAsync(shopId);
        if (shop == null)
            return NotFound(new { message = "Shop not found" });

        return Ok(new
        {
            shop.Id,
            shop.MerchantId,
            shop.Name,
            shop.Slug,
            Status = shop.Status.Name,
            Category = shop.Category?.Name,
            shop.Description,
            shop.CreatedAt,
            shop.UpdatedAt
        });
    }

    /// <summary>
    /// EN: Suspend a shop.
    /// VI: Tạm ngưng shop.
    /// </summary>
    [HttpPost("{shopId:guid}/suspend")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> SuspendShop(Guid shopId, [FromBody] AdminActionRequest request)
    {
        try
        {
            var shop = await _shopRepository.GetByIdAsync(shopId)
                ?? throw new DomainException("Shop not found");

            shop.SetInactive();

            _shopRepository.Update(shop);
            await _shopRepository.UnitOfWork.SaveEntitiesAsync();

            _logger.LogInformation("Shop {ShopId} suspended by Admin {AdminId}. Reason: {Reason}",
                shopId, GetAdminId(), request.Reason);

            return Ok(new { message = "Shop suspended successfully", shopId, status = shop.Status.Name });
        }
        catch (DomainException ex)
        {
            if (ex.Message.Contains("not found"))
                return NotFound(new { message = ex.Message });
            return BadRequest(new { message = ex.Message });
        }
    }

    /// <summary>
    /// EN: Reactivate a suspended shop.
    /// VI: Kích hoạt lại shop bị tạm ngưng.
    /// </summary>
    [HttpPost("{shopId:guid}/reactivate")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> ReactivateShop(Guid shopId)
    {
        try
        {
            var shop = await _shopRepository.GetByIdAsync(shopId)
                ?? throw new DomainException("Shop not found");

            shop.Publish();

            _shopRepository.Update(shop);
            await _shopRepository.UnitOfWork.SaveEntitiesAsync();

            _logger.LogInformation("Shop {ShopId} reactivated by Admin {AdminId}", shopId, GetAdminId());

            return Ok(new { message = "Shop reactivated successfully", shopId, status = shop.Status.Name });
        }
        catch (DomainException ex)
        {
            if (ex.Message.Contains("not found"))
                return NotFound(new { message = ex.Message });
            return BadRequest(new { message = ex.Message });
        }
    }

    /// <summary>
    /// EN: Close a shop permanently.
    /// VI: Đóng cửa shop vĩnh viễn.
    /// </summary>
    [HttpPost("{shopId:guid}/close")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> CloseShop(Guid shopId, [FromBody] AdminActionRequest request)
    {
        try
        {
            var shop = await _shopRepository.GetByIdAsync(shopId)
                ?? throw new DomainException("Shop not found");

            shop.Close();

            _shopRepository.Update(shop);
            await _shopRepository.UnitOfWork.SaveEntitiesAsync();

            _logger.LogWarning("Shop {ShopId} CLOSED by Admin {AdminId}. Reason: {Reason}",
                shopId, GetAdminId(), request.Reason);

            return Ok(new { message = "Shop closed successfully", shopId, status = shop.Status.Name });
        }
        catch (DomainException ex)
        {
            if (ex.Message.Contains("not found"))
                return NotFound(new { message = ex.Message });
            return BadRequest(new { message = ex.Message });
        }
    }

    private Guid GetAdminId()
    {
        var userIdClaim = User.FindFirst("sub")?.Value
            ?? User.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier")?.Value;
        return Guid.TryParse(userIdClaim, out var userId) ? userId : Guid.Empty;
    }
}
