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

using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using MerchantService.API.Application.Commands.Admin;
using MerchantService.API.Application.Queries.Admin;

namespace MerchantService.API.Controllers.Admin;

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

    public AdminMerchantsController(
        IMediator mediator,
        ILogger<AdminMerchantsController> logger)
    {
        _mediator = mediator;
        _logger = logger;
    }

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

    /// <summary>
    /// EN: Get merchant details by ID.
    /// VI: Lấy chi tiết merchant theo ID.
    /// </summary>
    [HttpGet("{merchantId:guid}")]
    [ProducesResponseType(typeof(AdminMerchantDetailDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> GetMerchantById(Guid merchantId)
    {
        try
        {
            var query = new GetMerchantDetailQuery(merchantId);
            var result = await _mediator.Send(query);
            return Ok(result);
        }
        catch (Domain.Exceptions.DomainException ex)
        {
            return NotFound(new { message = ex.Message });
        }
    }

    /// <summary>
    /// EN: Get merchant statistics.
    /// VI: Lấy thống kê merchant.
    /// </summary>
    [HttpGet("statistics")]
    [ProducesResponseType(typeof(AdminMerchantStatisticsDto), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetStatistics()
    {
        var query = new GetMerchantStatisticsQuery();
        var result = await _mediator.Send(query);
        return Ok(result);
    }

    /// <summary>
    /// EN: Approve merchant registration.
    /// VI: Phê duyệt đăng ký merchant.
    /// </summary>
    [HttpPost("{merchantId:guid}/approve")]
    [ProducesResponseType(typeof(ApproveMerchantResult), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> ApproveMerchant(Guid merchantId)
    {
        try
        {
            var command = new ApproveMerchantCommand(merchantId, GetAdminId());
            var result = await _mediator.Send(command);

            _logger.LogInformation("Merchant {MerchantId} approved by Admin {AdminId}", merchantId, GetAdminId());
            return Ok(result);
        }
        catch (Domain.Exceptions.DomainException ex)
        {
            if (ex.Message.Contains("not found"))
                return NotFound(new { message = ex.Message });
            return BadRequest(new { message = ex.Message });
        }
    }

    /// <summary>
    /// EN: Reject merchant registration.
    /// VI: Từ chối đăng ký merchant.
    /// </summary>
    [HttpPost("{merchantId:guid}/reject")]
    [ProducesResponseType(typeof(RejectMerchantResult), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> RejectMerchant(Guid merchantId, [FromBody] AdminActionRequest request)
    {
        try
        {
            var command = new RejectMerchantCommand(merchantId, request.Reason, GetAdminId());
            var result = await _mediator.Send(command);

            _logger.LogInformation("Merchant {MerchantId} rejected by Admin {AdminId}. Reason: {Reason}",
                merchantId, GetAdminId(), request.Reason);
            return Ok(result);
        }
        catch (Domain.Exceptions.DomainException ex)
        {
            if (ex.Message.Contains("not found"))
                return NotFound(new { message = ex.Message });
            return BadRequest(new { message = ex.Message });
        }
    }

    /// <summary>
    /// EN: Suspend an active merchant.
    /// VI: Tạm ngưng merchant đang hoạt động.
    /// </summary>
    [HttpPost("{merchantId:guid}/suspend")]
    [ProducesResponseType(typeof(SuspendMerchantResult), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> SuspendMerchant(Guid merchantId, [FromBody] AdminActionRequest request)
    {
        try
        {
            var command = new SuspendMerchantCommand(merchantId, request.Reason, GetAdminId());
            var result = await _mediator.Send(command);

            _logger.LogInformation("Merchant {MerchantId} suspended by Admin {AdminId}. Reason: {Reason}",
                merchantId, GetAdminId(), request.Reason);
            return Ok(result);
        }
        catch (Domain.Exceptions.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 merchant.
    /// VI: Kích hoạt lại merchant bị tạm ngưng.
    /// </summary>
    [HttpPost("{merchantId:guid}/reactivate")]
    [ProducesResponseType(typeof(ReactivateMerchantResult), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> ReactivateMerchant(Guid merchantId)
    {
        try
        {
            var command = new ReactivateMerchantCommand(merchantId, GetAdminId());
            var result = await _mediator.Send(command);

            _logger.LogInformation("Merchant {MerchantId} reactivated by Admin {AdminId}", merchantId, GetAdminId());
            return Ok(result);
        }
        catch (Domain.Exceptions.DomainException ex)
        {
            if (ex.Message.Contains("not found"))
                return NotFound(new { message = ex.Message });
            return BadRequest(new { message = ex.Message });
        }
    }

    /// <summary>
    /// EN: Permanently ban a merchant.
    /// VI: Cấm vĩnh viễn một merchant.
    /// </summary>
    [HttpPost("{merchantId:guid}/ban")]
    [ProducesResponseType(typeof(BanMerchantResult), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> BanMerchant(Guid merchantId, [FromBody] AdminActionRequest request)
    {
        try
        {
            var command = new BanMerchantCommand(merchantId, request.Reason, GetAdminId());
            var result = await _mediator.Send(command);

            _logger.LogWarning("Merchant {MerchantId} BANNED by Admin {AdminId}. Reason: {Reason}",
                merchantId, GetAdminId(), request.Reason);
            return Ok(result);
        }
        catch (Domain.Exceptions.DomainException ex)
        {
            if (ex.Message.Contains("not found"))
                return NotFound(new { message = ex.Message });
            return BadRequest(new { message = ex.Message });
        }
    }

    /// <summary>
    /// EN: Update a merchant's subscription plan.
    /// VI: Cập nhật gói đăng ký của merchant.
    /// </summary>
    [HttpPut("{merchantId:guid}/plan")]
    [ProducesResponseType(typeof(UpdateMerchantPlanResult), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> UpdateMerchantPlan(Guid merchantId, [FromBody] UpdatePlanRequest request)
    {
        var command = new UpdateMerchantPlanCommand(merchantId, request.PlanId);
        var result = await _mediator.Send(command);

        if (!result.Success)
            return BadRequest(new { success = false, error = new { message = result.Error } });

        _logger.LogInformation("Merchant {MerchantId} plan updated to {PlanName} by Admin {AdminId}",
            merchantId, result.PlanName, GetAdminId());
        return Ok(new { success = true, data = result });
    }

    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;
    }
}

#region Admin Request DTOs

/// <summary>
/// EN: Request for admin actions requiring a reason.
/// VI: Request cho các action admin cần lý do.
/// </summary>
public record AdminActionRequest(string Reason);
public record UpdatePlanRequest(int PlanId);

#endregion
