using Indotalent.ConfigBackEnd.Interfaces;
using Indotalent.Infrastructure.Database;
using MediatR;
using Microsoft.EntityFrameworkCore;

namespace Indotalent.Features.Setting.SystemUser.Cqrs;

public class GetSystemUserListResponse
{
    public string? Id { get; set; }
    public string? FullName { get; set; }
    public string? AvatarFile { get; set; }
    public string? Email { get; set; }
    public string? SsoIdFirebase { get; set; }
    public string? SsoIdKeycloak { get; set; }
    public bool IsActive { get; set; }
    public List<string> UserRoles { get; set; } = new();
}

public record GetSystemUserListQuery() : IRequest<List<GetSystemUserListResponse>>;

public class GetSystemUserListHandler : IRequestHandler<GetSystemUserListQuery, List<GetSystemUserListResponse>>
{
    private readonly AppDbContext _context;
    private readonly ICurrentUserService _currentUserService;

    public GetSystemUserListHandler(AppDbContext context, ICurrentUserService currentUserService)
    {
        _context = context;
        _currentUserService = currentUserService;
    }

    public async Task<List<GetSystemUserListResponse>> Handle(GetSystemUserListQuery request, CancellationToken cancellationToken)
    {
        var currentTenantId = _currentUserService.TenantId;

        // Get user IDs that belong to the current tenant via TenantUser
        var tenantUserIds = await _context.TenantUser
            .AsNoTracking()
            .Where(x => x.TenantId == currentTenantId)
            .Select(x => x.UserId)
            .ToListAsync(cancellationToken);

        var users = await _context.Users
            .AsNoTracking()
            .Where(x => tenantUserIds.Contains(x.Id))
            .OrderByDescending(x => x.CreatedAt)
            .Select(x => new GetSystemUserListResponse
            {
                Id = x.Id,
                FullName = x.FullName,
                Email = x.Email,
                SsoIdFirebase = x.SsoIdFirebase,
                SsoIdKeycloak = x.SsoIdKeycloak,
                IsActive = x.IsActive,
                AvatarFile = x.AvatarFile,
            })
            .ToListAsync(cancellationToken);

        var userIds = users.Select(u => u.Id).ToList();

        var userRolesMap = await (from ur in _context.UserRoles
                                  join r in _context.Roles on ur.RoleId equals r.Id
                                  where userIds.Contains(ur.UserId)
                                  select new { ur.UserId, r.Name })
                                  .ToListAsync(cancellationToken);

        foreach (var user in users)
        {
            user.UserRoles = userRolesMap
                .Where(x => x.UserId == user.Id)
                .Select(x => x.Name!)
                .ToList();
        }

        return users;
    }
}