// EN: Merchants Controller for merchant management.
// VI: Controller Merchants để quản lý merchant.

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

namespace MerchantService.API.Controllers;

/// <summary>
/// EN: Controller for merchant management.
/// VI: Controller để quản lý merchant.
/// </summary>
[ApiController]
[Route("api/v1/merchants")]
[Authorize]
public class MerchantsController : MerchantBaseController
{
    private readonly IMediator _mediator;
    private readonly ILogger<MerchantsController> _logger;

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

    /// <summary>
    /// EN: Get current merchant's profile.
    /// VI: Lấy profile của merchant hiện tại.
    /// </summary>
    [HttpGet("me")]
    [ProducesResponseType(typeof(MerchantProfileDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> GetProfile()
    {
        var userId = GetCurrentUserId();
        var result = await _mediator.Send(new GetMerchantProfileQuery(userId));
        if (result == null)
        {
            return NotFound(new { message = "Merchant profile not found. Please register first." });
        }
        return Ok(result);
    }

    /// <summary>
    /// EN: Register as a new merchant.
    /// VI: Đăng ký làm merchant mới.
    /// </summary>
    [HttpPost("register")]
    [ProducesResponseType(typeof(RegisterMerchantResult), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status409Conflict)]
    public async Task<IActionResult> Register([FromBody] RegisterMerchantCommand command)
    {
        try
        {
            var userId = GetCurrentUserId();
            var cmd = command with { UserId = userId };
            var result = await _mediator.Send(cmd);
            _logger.LogInformation("Merchant registered: {MerchantId}", result.MerchantId);
            return CreatedAtAction(nameof(GetProfile), result);
        }
        catch (Domain.Exceptions.DomainException ex) when (ex.Message.Contains("already has"))
        {
            return Conflict(new { message = ex.Message });
        }
    }

    /// <summary>
    /// EN: Update merchant information.
    /// VI: Cập nhật thông tin merchant.
    /// </summary>
    [HttpPut("me")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> UpdateProfile([FromBody] UpdateMerchantCommand command)
    {
        var userId = GetCurrentUserId();
        var cmd = command with { UserId = userId };
        await _mediator.Send(cmd);
        return Ok(new { message = "Profile updated successfully" });
    }

    /// <summary>
    /// EN: Submit for verification.
    /// VI: Nộp hồ sơ xác minh.
    /// </summary>
    [HttpPost("me/verify")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> SubmitVerification()
    {
        var userId = GetCurrentUserId();
        await _mediator.Send(new SubmitMerchantVerificationCommand(userId));
        return Ok(new { message = "Verification submitted successfully. Please wait for admin approval." });
    }

    /// <summary>
    /// EN: Get all shops for a merchant with pagination and optional status filter.
    /// VI: Lấy tất cả shops của merchant với phân trang và lọc theo trạng thái (tùy chọn).
    /// </summary>
    [HttpGet("{merchantId:guid}/shops")]
    [ProducesResponseType(typeof(GetMerchantShopsQueryResult), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> GetMerchantShops(
        Guid merchantId,
        [FromQuery] string? status,
        [FromQuery] int page = 1,
        [FromQuery] int pageSize = 20)
    {
        try
        {
            var result = await _mediator.Send(new GetMerchantShopsQuery(merchantId, status, page, pageSize));
            return Ok(new { success = true, data = result });
        }
        catch (Domain.Exceptions.DomainException ex) when (ex.Message.Contains("not found"))
        {
            return NotFound(new { success = false, error = new { code = "MERCHANT_NOT_FOUND", message = ex.Message } });
        }
        catch (Domain.Exceptions.DomainException ex) when (ex.Message.Contains("Invalid status"))
        {
            return BadRequest(new { success = false, error = new { code = "INVALID_STATUS_FILTER", message = ex.Message } });
        }
    }

    /// <summary>
    /// EN: Set a shop as the default/primary shop for the merchant.
    /// VI: Đặt shop làm shop mặc định/chính cho merchant.
    /// </summary>
    [HttpPut("{merchantId:guid}/shops/{shopId:guid}/set-default")]
    [ProducesResponseType(typeof(SetDefaultShopResult), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> SetDefaultShop(Guid merchantId, Guid shopId)
    {
        try
        {
            var result = await _mediator.Send(new SetDefaultShopCommand(merchantId, shopId));
            return Ok(new { success = true, data = result });
        }
        catch (Domain.Exceptions.DomainException ex) when (ex.Message.Contains("not found"))
        {
            return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = ex.Message } });
        }
        catch (Domain.Exceptions.DomainException ex) when (ex.Message.Contains("does not belong"))
        {
            return BadRequest(new { success = false, error = new { code = "SHOP_NOT_OWNED", message = ex.Message } });
        }
        catch (Domain.Exceptions.DomainException ex)
        {
            return BadRequest(new { success = false, error = new { code = "SET_DEFAULT_FAILED", message = ex.Message } });
        }
    }

    /// <summary>
    /// EN: Transfer shop ownership to another merchant.
    /// VI: Chuyển quyền sở hữu shop cho merchant khác.
    /// </summary>
    [HttpPost("{merchantId:guid}/shops/{shopId:guid}/transfer")]
    [ProducesResponseType(typeof(TransferShopResult), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> TransferShop(
        Guid merchantId,
        Guid shopId,
        [FromBody] TransferShopRequest request)
    {
        try
        {
            var command = new TransferShopCommand
            {
                MerchantId = merchantId,
                ShopId = shopId,
                NewMerchantId = request.NewMerchantId,
                Reason = request.Reason
            };
            var result = await _mediator.Send(command);
            _logger.LogInformation(
                "Shop {ShopId} transferred from merchant {OldMerchantId} to {NewMerchantId}",
                shopId, merchantId, request.NewMerchantId);
            return Ok(new { success = true, data = result });
        }
        catch (Domain.Exceptions.DomainException ex) when (ex.Message.Contains("not found"))
        {
            return NotFound(new { success = false, error = new { code = "NOT_FOUND", message = ex.Message } });
        }
        catch (Domain.Exceptions.DomainException ex) when (ex.Message.Contains("permission") || ex.Message.Contains("does not belong"))
        {
            return StatusCode(StatusCodes.Status403Forbidden, new { success = false, error = new { code = "FORBIDDEN", message = ex.Message } });
        }
        catch (Domain.Exceptions.DomainException ex)
        {
            return BadRequest(new { success = false, error = new { code = "TRANSFER_FAILED", message = ex.Message } });
        }
    }
}

/// <summary>
/// EN: Request model for shop transfer.
/// VI: Model request để chuyển shop.
/// </summary>
public record TransferShopRequest
{
    /// <summary>
    /// EN: New owner merchant ID.
    /// VI: ID merchant chủ sở hữu mới.
    /// </summary>
    public Guid NewMerchantId { get; init; }

    /// <summary>
    /// EN: Reason for transfer (optional).
    /// VI: Lý do chuyển (tùy chọn).
    /// </summary>
    public string? Reason { get; init; }
}

/// <summary>
/// EN: Command to submit merchant for verification.
/// VI: Command để nộp merchant xác minh.
/// </summary>
public record SubmitMerchantVerificationCommand(Guid UserId) : IRequest<bool>;

/// <summary>
/// EN: Handler for SubmitMerchantVerificationCommand.
/// VI: Handler cho SubmitMerchantVerificationCommand.
/// </summary>
public class SubmitMerchantVerificationCommandHandler : IRequestHandler<SubmitMerchantVerificationCommand, bool>
{
    private readonly Domain.AggregatesModel.MerchantAggregate.IMerchantRepository _merchantRepository;

    public SubmitMerchantVerificationCommandHandler(
        Domain.AggregatesModel.MerchantAggregate.IMerchantRepository merchantRepository)
    {
        _merchantRepository = merchantRepository;
    }

    public async Task<bool> Handle(SubmitMerchantVerificationCommand request, CancellationToken cancellationToken)
    {
        // EN: Use user ID passed from the controller
        // VI: Dùng user ID được truyền từ controller
        var merchant = await _merchantRepository.GetByUserIdAsync(request.UserId, cancellationToken)
            ?? throw new Domain.Exceptions.DomainException("Merchant not found");

        merchant.SubmitForVerification();
        _merchantRepository.Update(merchant);
        await _merchantRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

        return true;
    }
}
