// EN: Handlers for Shop status change commands.
// VI: Handlers cho các commands thay đổi trạng thái Shop.

using MediatR;
using MerchantService.Domain.AggregatesModel.MerchantAggregate;
using MerchantService.Domain.AggregatesModel.ShopAggregate;
using MerchantService.Domain.Exceptions;

namespace MerchantService.API.Application.Commands.Shops;

/// <summary>
/// EN: Handler for publishing a shop.
/// VI: Handler để công khai shop.
/// </summary>
public class PublishShopCommandHandler : IRequestHandler<PublishShopCommand, bool>
{
    private readonly IMerchantRepository _merchantRepository;
    private readonly IShopRepository _shopRepository;
    private readonly ILogger<PublishShopCommandHandler> _logger;

    public PublishShopCommandHandler(
        IMerchantRepository merchantRepository,
        IShopRepository shopRepository,
        ILogger<PublishShopCommandHandler> logger)
    {
        _merchantRepository = merchantRepository;
        _shopRepository = shopRepository;
        _logger = logger;
    }

    public async Task<bool> Handle(PublishShopCommand request, CancellationToken cancellationToken)
    {
        var (merchant, shop) = await ValidateOwnershipAsync(request.UserId, request.ShopId, cancellationToken);

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

        _logger.LogInformation("Shop published: {ShopId}", shop.Id);
        return true;
    }

    private async Task<(Merchant, Shop)> ValidateOwnershipAsync(Guid userId, Guid shopId, CancellationToken cancellationToken)
    {
        var merchant = await _merchantRepository.GetByUserIdAsync(userId, cancellationToken)
            ?? throw new DomainException("Merchant not found");

        var shop = await _shopRepository.GetByIdAsync(shopId, cancellationToken)
            ?? throw new DomainException("Shop not found");

        if (shop.MerchantId != merchant.Id)
            throw new DomainException("You don't have permission to modify this shop");

        return (merchant, shop);
    }
}

/// <summary>
/// EN: Handler for setting a shop as inactive.
/// VI: Handler để đặt shop không hoạt động.
/// </summary>
public class SetShopInactiveCommandHandler : IRequestHandler<SetShopInactiveCommand, bool>
{
    private readonly IMerchantRepository _merchantRepository;
    private readonly IShopRepository _shopRepository;
    private readonly ILogger<SetShopInactiveCommandHandler> _logger;

    public SetShopInactiveCommandHandler(
        IMerchantRepository merchantRepository,
        IShopRepository shopRepository,
        ILogger<SetShopInactiveCommandHandler> logger)
    {
        _merchantRepository = merchantRepository;
        _shopRepository = shopRepository;
        _logger = logger;
    }

    public async Task<bool> Handle(SetShopInactiveCommand 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 DomainException("Merchant not found");

        var shop = await _shopRepository.GetByIdAsync(request.ShopId, cancellationToken)
            ?? throw new DomainException("Shop not found");

        if (shop.MerchantId != merchant.Id)
            throw new DomainException("You don't have permission to modify this shop");

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

        _logger.LogInformation("Shop set inactive: {ShopId}", shop.Id);
        return true;
    }
}

/// <summary>
/// EN: Handler for closing a shop permanently.
/// VI: Handler để đóng cửa shop vĩnh viễn.
/// </summary>
public class CloseShopCommandHandler : IRequestHandler<CloseShopCommand, bool>
{
    private readonly IMerchantRepository _merchantRepository;
    private readonly IShopRepository _shopRepository;
    private readonly ILogger<CloseShopCommandHandler> _logger;

    public CloseShopCommandHandler(
        IMerchantRepository merchantRepository,
        IShopRepository shopRepository,
        ILogger<CloseShopCommandHandler> logger)
    {
        _merchantRepository = merchantRepository;
        _shopRepository = shopRepository;
        _logger = logger;
    }

    public async Task<bool> Handle(CloseShopCommand 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 DomainException("Merchant not found");

        var shop = await _shopRepository.GetByIdAsync(request.ShopId, cancellationToken)
            ?? throw new DomainException("Shop not found");

        if (shop.MerchantId != merchant.Id)
            throw new DomainException("You don't have permission to modify this shop");

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

        _logger.LogInformation("Shop closed: {ShopId}", shop.Id);
        return true;
    }
}
