using System.Transactions;
using SIGCM2.Application.Abstractions;
using SIGCM2.Application.Abstractions.Persistence;
using SIGCM2.Application.Audit;
using SIGCM2.Application.Roles.Dtos;
using SIGCM2.Domain.Exceptions;

namespace SIGCM2.Application.Roles.Deactivate;

public sealed class DeactivateRolCommandHandler : ICommandHandler<DeactivateRolCommand, RolDto>
{
    private readonly IRolRepository _repository;
    private readonly IAuditLogger _audit;

    public DeactivateRolCommandHandler(IRolRepository repository, IAuditLogger audit)
    {
        _repository = repository;
        _audit = audit;
    }

    public async Task<RolDto> Handle(DeactivateRolCommand command)
    {
        var existing = await _repository.GetByCodigoAsync(command.Codigo)
            ?? throw new RolNotFoundException(command.Codigo);

        // Guard: block soft-delete when active usuarios reference this rol.
        if (await _repository.HasActiveUsuariosAsync(command.Codigo))
            throw new RolInUseException(command.Codigo);

        using (var tx = new TransactionScope(
            TransactionScopeOption.Required,
            new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted },
            TransactionScopeAsyncFlowOption.Enabled))
        {
            var updated = await _repository.UpdateAsync(
                existing.Codigo, existing.Nombre, existing.Descripcion, activo: false);
            if (!updated)
                throw new RolNotFoundException(command.Codigo);

            await _audit.LogAsync(
                action: "rol.deactivate",
                targetType: "Rol",
                targetId: existing.Id.ToString());

            tx.Complete();
        }

        var rol = await _repository.GetByCodigoAsync(command.Codigo)
            ?? throw new RolNotFoundException(command.Codigo);

        return new RolDto(rol.Id, rol.Codigo, rol.Nombre, rol.Descripcion, rol.Activo, rol.FechaCreacion, rol.FechaModificacion);
    }
}
