// EN: Commands for branch management - Update and Delete.
// VI: Commands cho quản lý chi nhánh - Cập nhật và Xóa.

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

namespace MerchantService.API.Application.Commands.Shops;

#region Update Branch Command

/// <summary>
/// EN: Command to update an existing branch.
/// VI: Command để cập nhật chi nhánh.
/// </summary>
public record UpdateBranchCommand : IRequest<bool>
{
    public Guid UserId { get; init; }
    public Guid ShopId { get; init; }
    public Guid BranchId { get; init; }
    public string Name { get; init; } = null!;
    public string? Code { get; init; }
    public string Street { get; init; } = null!;
    public string? Ward { get; init; }
    public string District { get; init; } = null!;
    public string City { get; init; } = null!;
    public string? Province { get; init; }
    public double? Latitude { get; init; }
    public double? Longitude { get; init; }
    public string? Phone { get; init; }
}

/// <summary>
/// EN: Handler for UpdateBranchCommand.
/// VI: Handler cho UpdateBranchCommand.
/// </summary>
public class UpdateBranchCommandHandler : IRequestHandler<UpdateBranchCommand, bool>
{
    private readonly IMerchantRepository _merchantRepository;
    private readonly IShopRepository _shopRepository;
    private readonly ILogger<UpdateBranchCommandHandler> _logger;

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

    public async Task<bool> Handle(UpdateBranchCommand 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 do not have permission to update this shop");

        var branch = shop.Branches.FirstOrDefault(b => b.Id == request.BranchId)
            ?? throw new DomainException("Branch not found");

        // EN: Build address using record with init
        // VI: Xây dựng địa chỉ sử dụng record với init
        var address = new Address
        {
            Street = request.Street,
            Ward = request.Ward,
            District = request.District,
            City = request.City,
            Province = request.Province
        };

        GeoLocation? location = null;
        if (request.Latitude.HasValue && request.Longitude.HasValue)
        {
            location = new GeoLocation
            {
                Latitude = request.Latitude.Value,
                Longitude = request.Longitude.Value
            };
        }

        // EN: Update branch
        // VI: Cập nhật chi nhánh
        branch.Update(request.Name, request.Code, address, location);
        if (!string.IsNullOrWhiteSpace(request.Phone))
            branch.SetPhone(request.Phone);

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

        _logger.LogInformation("Branch {BranchId} updated in Shop {ShopId}", request.BranchId, request.ShopId);
        return true;
    }
}

#endregion

#region Delete Branch Command

/// <summary>
/// EN: Command to delete a branch.
/// VI: Command để xóa chi nhánh.
/// </summary>
public record DeleteBranchCommand(Guid ShopId, Guid BranchId, Guid UserId) : IRequest<bool>;

/// <summary>
/// EN: Handler for DeleteBranchCommand.
/// VI: Handler cho DeleteBranchCommand.
/// </summary>
public class DeleteBranchCommandHandler : IRequestHandler<DeleteBranchCommand, bool>
{
    private readonly IMerchantRepository _merchantRepository;
    private readonly IShopRepository _shopRepository;
    private readonly ILogger<DeleteBranchCommandHandler> _logger;

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

    public async Task<bool> Handle(DeleteBranchCommand 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 do not have permission to modify this shop");

        shop.RemoveBranch(request.BranchId);

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

        _logger.LogInformation("Branch {BranchId} removed from Shop {ShopId}", request.BranchId, request.ShopId);
        return true;
    }
}

#endregion
