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

namespace Indotalent.Features.Setting.SystemUser.Cqrs;

public class GetSystemUserByIdResponse
{
    public string? Id { get; set; }
    public string? FullName { get; set; }
    public string? Email { get; set; }
    public string? PhoneNumber { get; set; }
    public string? UserName { get; set; }
    public bool EmailConfirmed { get; set; }
    public bool PhoneNumberConfirmed { get; set; }
    public bool TwoFactorEnabled { get; set; }
    public bool IsActive { get; set; }
    public bool LockoutEnabled { get; set; }
    public DateTimeOffset? LockoutEnd { get; set; }
    public int AccessFailedCount { get; set; }
    public string? SsoIdFirebase { get; set; }
    public string? SsoIdKeycloak { get; set; }
    public string? SsoIdAzure { get; set; }
    public string? SsoIdAws { get; set; }
    public string? SsoIdOther1 { get; set; }
    public string? SsoIdOther2 { get; set; }
    public string? SsoIdOther3 { get; set; }
    public DateTime CreatedAt { get; set; }
    public DateTime? LastLoginAt { get; set; }
    public DateTime? UpdatedAt { get; set; }
    public List<string> UserRoles { get; set; } = new();
    public string? AvatarFile { get; set; }
}

public record GetSystemUserByIdQuery(string Id) : IRequest<GetSystemUserByIdResponse?>;

public class GetSystemUserByIdHandler : IRequestHandler<GetSystemUserByIdQuery, GetSystemUserByIdResponse?>
{
    private readonly AppDbContext _context;

    public GetSystemUserByIdHandler(AppDbContext context) => _context = context;

    public async Task<GetSystemUserByIdResponse?> Handle(GetSystemUserByIdQuery request, CancellationToken cancellationToken)
    {
        var user = await _context.Users
            .AsNoTracking()
            .Where(x => x.Id == request.Id)
            .Select(x => new GetSystemUserByIdResponse
            {
                Id = x.Id,
                FullName = x.FullName,
                Email = x.Email,
                PhoneNumber = x.PhoneNumber,
                UserName = x.UserName,
                EmailConfirmed = x.EmailConfirmed,
                PhoneNumberConfirmed = x.PhoneNumberConfirmed,
                TwoFactorEnabled = x.TwoFactorEnabled,
                IsActive = x.IsActive,
                LockoutEnabled = x.LockoutEnabled,
                LockoutEnd = x.LockoutEnd,
                AccessFailedCount = x.AccessFailedCount,
                SsoIdFirebase = x.SsoIdFirebase,
                SsoIdKeycloak = x.SsoIdKeycloak,
                SsoIdAzure = x.SsoIdAzure,
                SsoIdAws = x.SsoIdAws,
                SsoIdOther1 = x.SsoIdOther1,
                SsoIdOther2 = x.SsoIdOther2,
                SsoIdOther3 = x.SsoIdOther3,
                CreatedAt = x.CreatedAt,
                LastLoginAt = x.LastLoginAt,
                UpdatedAt = x.UpdatedAt,
                AvatarFile = x.AvatarFile,
            })
            .FirstOrDefaultAsync(cancellationToken);

        if (user == null) return null;

        user.UserRoles = await (from ur in _context.UserRoles
                                join r in _context.Roles on ur.RoleId equals r.Id
                                where ur.UserId == user.Id
                                select r.Name!)
                                .ToListAsync(cancellationToken);

        return user;
    }
}