namespace Csr.Infrastructure.Persistence.Repositories;

using CSR.Domain.Entities;
using CSR.Application.Interfaces;
using Microsoft.EntityFrameworkCore;

public class UserRepository(CSR.Infrastructure.Persistence.CSRDbContext context) : IUserRepository
{
  private readonly CSR.Infrastructure.Persistence.CSRDbContext _context = context;

  public async Task<User?> GetByIdAsync(int id)
  {
    var userEntity = await _context.Users
        .Include(u => u.Role)
        .SingleOrDefaultAsync(u => u.Id == id);

    if (userEntity == null)
    {
      return null; // No entity found, return null domain model
    }

    var user = User.LoadExisting(
        userEntity.Id,
        userEntity.Username,
        userEntity.Email,
        userEntity.PasswordHash,
        userEntity.RoleId,
        Role.LoadExisting(
          userEntity.Role.Id,
          userEntity.Role.Name
          )
    );

    return user;
  }


  public async Task AddAsync(User user)
  {
    var userEntity = new CSR.Infrastructure.Persistence.User
    {
      Username = user.Username,
      Email = user.Email,
      PasswordHash = user.PasswordHash,
      RoleId = user.RoleId,
      Role = new CSR.Infrastructure.Persistence.Role
      {
        Id = user.Role.Id,
        Name = user.Role.Name
      }
    };

    _context.Users.Add(userEntity);
    await _context.SaveChangesAsync();
  }


  public async Task UpdateAsync(User user)
  {
    var userEntity = await _context.Users
        .Include(u => u.Role)
        .FirstOrDefaultAsync(u => u.Id == user.Id);

    if (userEntity == null)
    {
      // NOTE should I throw an exception here?
      return;
    }


    userEntity.Id = user.Id;
    userEntity.Username = user.Username;
    userEntity.Email = user.Email;
    userEntity.PasswordHash = user.PasswordHash;
    userEntity.RoleId = user.RoleId;
    userEntity.Role = new CSR.Infrastructure.Persistence.Role { Id = user.Role.Id, Name = user.Role.Name };

    // Prevent EF from trying to update the Role entity
    _context.Entry(userEntity.Role).State = EntityState.Unchanged;

    _context.Users.Update(userEntity);
    await _context.SaveChangesAsync();
  }


  public async Task DeleteAsync(int id)
  {
    var userEntity = new CSR.Infrastructure.Persistence.User
    {
      Id = id,
      Username = string.Empty,
      Email = string.Empty,
      PasswordHash = string.Empty,
      RoleId = 0,
      Role = new CSR.Infrastructure.Persistence.Role
      {
        Id = 0,
        Name = string.Empty
      }
    };

    _context.Users.Remove(userEntity);
    await _context.SaveChangesAsync();
  }
}
