using Brizco.Domain.Entities.Complex;
using Brizco.Domain.Entities.User;
using Microsoft.AspNetCore.Identity;

namespace Brizco.Repository.Handlers.Complex;

public class CreateComplexUserCommandHandler : IRequestHandler<CreateComplexUserCommand, ComplexUserSDto>
{
    private readonly IRepositoryWrapper _repositoryWrapper;
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly RoleManager<ApplicationRole> _roleManager;
    private readonly ILogger<CreateComplexUserCommandHandler> _logger;

    public CreateComplexUserCommandHandler(IRepositoryWrapper repositoryWrapper,
        UserManager<ApplicationUser> userManager,
        RoleManager<ApplicationRole> roleManager,
        ILogger<CreateComplexUserCommandHandler> logger)
    {
        _repositoryWrapper = repositoryWrapper;
        _userManager = userManager;
        _roleManager = roleManager;
        _logger = logger;
    }

    public async Task<ComplexUserSDto> Handle(CreateComplexUserCommand request, CancellationToken cancellationToken)
    {
        try
        {
            //await _repositoryWrapper.BeginTransaction(cancellationToken);
            var complex = await _repositoryWrapper.SetRepository<Domain.Entities.Complex.Complex>().TableNoTracking
                .FirstOrDefaultAsync(c => c.Id == request.ComplexId, cancellationToken);
            if (complex == null)
                throw new AppException("Complex not found", ApiResultStatusCode.NotFound);

            var user = await _userManager.FindByIdAsync(request.UserId.ToString());
            if (user == null)
                throw new AppException("User not found", ApiResultStatusCode.NotFound);
            var complexUser = await _repositoryWrapper.SetRepository<ComplexUser>()
                .TableNoTracking
                .FirstOrDefaultAsync(f => f.ComplexId == request.ComplexId && f.UserId == request.UserId, cancellationToken);
            if (complexUser != null)
                throw new AppException("این کاربر در این رستوران وجود دارد");

            complexUser = complex.AddComplexUser(request.UserId);
            foreach (var roleId in request.RoleIds)
            {
                var role = await _roleManager.FindByIdAsync(roleId.ToString());
                var result = await _userManager.AddToRoleAsync(user, role.Name);
                if (!result.Succeeded)
                    throw new AppException(string.Join('|', result.Errors));
                complexUser.AddRole(role.Id);
            }

            _repositoryWrapper.SetRepository<ComplexUser>().Add(complexUser);
            await _repositoryWrapper.SaveChangesAsync(cancellationToken);
            //await _repositoryWrapper.CommitAsync(cancellationToken);
            return complexUser.AdaptToSDto();
        }
        catch (Exception)
        {
            await _repositoryWrapper.RollBackAsync(cancellationToken);
            throw;
        }
    }
}