// EN: Staff queries.
// VI: Queries cho nhân viên.

using MediatR;
using MerchantService.Domain.AggregatesModel.MerchantAggregate;
using MerchantService.Domain.AggregatesModel.MerchantStaffAggregate;
using MerchantService.Domain.Exceptions;
using MerchantService.Domain.SeedWork;

namespace MerchantService.API.Application.Queries.Staff;

#region Get My Staff Query

/// <summary>
/// EN: Query to get current merchant's staff list.
/// VI: Query để lấy danh sách nhân viên của merchant hiện tại.
/// </summary>
public record GetMyStaffQuery(Guid UserId) : IRequest<IReadOnlyList<StaffDto>>;

/// <summary>
/// EN: Handler for GetMyStaffQuery.
/// VI: Handler cho GetMyStaffQuery.
/// </summary>
public class GetMyStaffQueryHandler : IRequestHandler<GetMyStaffQuery, IReadOnlyList<StaffDto>>
{
    private readonly IMerchantRepository _merchantRepository;
    private readonly IMerchantStaffRepository _staffRepository;

    public GetMyStaffQueryHandler(
        IMerchantRepository merchantRepository,
        IMerchantStaffRepository staffRepository)
    {
        _merchantRepository = merchantRepository;
        _staffRepository = staffRepository;
    }

    public async Task<IReadOnlyList<StaffDto>> Handle(GetMyStaffQuery 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);

        // EN: If user is not a merchant owner, try to find merchant through staff membership
        // VI: Nếu user không phải chủ merchant, thử tìm merchant qua tư cách nhân viên
        if (merchant == null)
        {
            var staffMember = await _staffRepository.GetByUserIdAsync(request.UserId, cancellationToken);
            if (staffMember != null)
                merchant = await _merchantRepository.GetByIdAsync(staffMember.MerchantId, cancellationToken);
        }

        if (merchant == null)
            throw new DomainException("Merchant not found / Không tìm thấy merchant");

        var staffList = await _staffRepository.GetByMerchantIdAsync(merchant.Id, cancellationToken);

        return staffList.Select(s => new StaffDto
        {
            Id = s.Id,
            UserId = s.UserId,
            Email = s.Email ?? string.Empty,
            EmployeeCode = s.EmployeeCode,
            Phone = s.Phone,
            FirstName = s.FirstName,
            LastName = s.LastName,
            Address = s.Address,
            ProfilePhotoUrl = s.ProfilePhotoUrl,
            DocumentFrontUrl = s.DocumentFrontUrl,
            DocumentBackUrl = s.DocumentBackUrl,
            Role = Enumeration.FromValue<StaffRole>(s.RoleId).Name,
            Status = Enumeration.FromValue<StaffStatus>(s.StatusId).Name,
            Permissions = (int)s.Permissions,
            HasPinCode = !string.IsNullOrEmpty(s.PinCodeHash),
            CreatedAt = s.CreatedAt,
            UpdatedAt = s.UpdatedAt,
            ShopAssignments = s.ShopAssignments.Select(sm => new ShopAssignmentDto
            {
                ShopId = sm.ShopId,
                ShopRole = Enumeration.FromValue<ShopRole>(sm.RoleId).Name,
                BranchId = sm.BranchId
            }).ToList()
        }).ToList();
    }
}

#endregion

#region Staff DTOs

/// <summary>
/// EN: Staff DTO.
/// VI: DTO nhân viên.
/// </summary>
public record StaffDto
{
    public Guid Id { get; init; }
    public Guid? UserId { get; init; }
    public string Email { get; init; } = null!;
    public string? EmployeeCode { get; init; }
    public string? Phone { get; init; }
    public string? FirstName { get; init; }
    public string? LastName { get; init; }
    public string? Address { get; init; }
    public string? ProfilePhotoUrl { get; init; }
    public string? DocumentFrontUrl { get; init; }
    public string? DocumentBackUrl { get; init; }
    public string Role { get; init; } = null!;
    public string Status { get; init; } = null!;
    public int Permissions { get; init; }
    public bool HasPinCode { get; init; }
    public DateTime CreatedAt { get; init; }
    public DateTime? UpdatedAt { get; init; }
    public List<ShopAssignmentDto> ShopAssignments { get; init; } = [];
}

/// <summary>
/// EN: Shop assignment DTO.
/// VI: DTO gán shop.
/// </summary>
public record ShopAssignmentDto
{
    public Guid ShopId { get; init; }
    public string ShopRole { get; init; } = null!;
    public Guid? BranchId { get; init; }
}

#endregion
