// EN: Query to get attendance records for a staff member or shop.
// VI: Query lấy bản ghi chấm công cho nhân viên hoặc cửa hàng.

using MediatR;
using MerchantService.Domain.AggregatesModel.AttendanceAggregate;
using MerchantService.Domain.AggregatesModel.MerchantStaffAggregate;

namespace MerchantService.API.Application.Queries.Attendance;

public record GetAttendanceByStaffQuery(Guid StaffId, int Month, int Year) : IRequest<List<AttendanceDto>>;
public record GetAttendanceByShopQuery(Guid ShopId, int Month, int Year) : IRequest<List<AttendanceDto>>;

/// <summary>
/// EN: Attendance DTO with optional StaffName for admin views.
/// VI: DTO chấm công có StaffName tùy chọn cho view admin.
/// </summary>
public record AttendanceDto(Guid Id, Guid StaffId, string? StaffName, DateTime Date, DateTime? CheckIn, DateTime? CheckOut,
    decimal? HoursWorked, string Status, string? Notes);

public class GetAttendanceByStaffQueryHandler : IRequestHandler<GetAttendanceByStaffQuery, List<AttendanceDto>>
{
    private readonly IAttendanceRepository _repo;

    public GetAttendanceByStaffQueryHandler(IAttendanceRepository repo) => _repo = repo;

    public async Task<List<AttendanceDto>> Handle(GetAttendanceByStaffQuery request, CancellationToken ct)
    {
        var records = await _repo.GetByStaffAndMonthAsync(request.StaffId, request.Month, request.Year, ct);
        return records.Select(r => new AttendanceDto(r.Id, r.StaffId, null, r.Date, r.CheckIn, r.CheckOut,
            r.HoursWorked, r.Status, r.Notes)).ToList();
    }
}

/// <summary>
/// EN: Handler for shop attendance — joins with MerchantStaff to include staff names.
/// VI: Handler chấm công cửa hàng — join MerchantStaff để lấy tên nhân viên.
/// </summary>
public class GetAttendanceByShopQueryHandler : IRequestHandler<GetAttendanceByShopQuery, List<AttendanceDto>>
{
    private readonly IAttendanceRepository _repo;
    private readonly IMerchantStaffRepository _staffRepo;

    public GetAttendanceByShopQueryHandler(IAttendanceRepository repo, IMerchantStaffRepository staffRepo)
    {
        _repo = repo;
        _staffRepo = staffRepo;
    }

    public async Task<List<AttendanceDto>> Handle(GetAttendanceByShopQuery request, CancellationToken ct)
    {
        var records = await _repo.GetByShopAndMonthAsync(request.ShopId, request.Month, request.Year, ct);

        // EN: Load staff names for all unique staffIds in this batch.
        // VI: Tải tên nhân viên cho tất cả staffId duy nhất trong batch này.
        var staffIds = records.Select(r => r.StaffId).Distinct().ToList();
        var staffList = await _staffRepo.GetByIdsAsync(staffIds, ct);
        var staffNames = staffList.ToDictionary(s => s.Id, s => $"{s.FirstName} {s.LastName}".Trim());

        return records.Select(r => new AttendanceDto(r.Id, r.StaffId,
            staffNames.TryGetValue(r.StaffId, out var name) ? name : null,
            r.Date, r.CheckIn, r.CheckOut, r.HoursWorked, r.Status, r.Notes)).ToList();
    }
}
