using System.Data; using AMREZ.EOP.Abstractions.Applications.Tenancy; using AMREZ.EOP.Abstractions.Applications.UseCases.Tenancy; using AMREZ.EOP.Abstractions.Infrastructures.Common; using AMREZ.EOP.Abstractions.Infrastructures.Repositories; using AMREZ.EOP.Contracts.DTOs.Tenancy.CreateTenant; using AMREZ.EOP.Domain.Entities.Tenancy; using Microsoft.AspNetCore.Http; namespace AMREZ.EOP.Application.UseCases.Tenancy; public sealed class CreateTenantUseCase : ICreateTenantUseCase { private readonly ITenantResolver _resolver; private readonly IHttpContextAccessor _http; private readonly IUnitOfWork _uow; private readonly ITenantRepository _repo; private readonly ITenantProvisioner _provisioner; public CreateTenantUseCase( ITenantResolver resolver, IHttpContextAccessor http, IUnitOfWork uow, ITenantRepository repo, ITenantProvisioner provisioner ) { _resolver = resolver; _http = http; _uow = uow; _repo = repo; _provisioner = provisioner; } public async Task ExecuteAsync(CreateTenantRequest request, CancellationToken ct = default) { var http = _http.HttpContext ?? throw new InvalidOperationException("No HttpContext"); var tenant = _resolver.Resolve(http, request); if (tenant is null) return null; await _uow.BeginAsync(tenant, IsolationLevel.ReadCommitted, ct); try { var key = request.TenantKey.Trim().ToLowerInvariant(); if (await _repo.TenantExistsAsync(key, ct)) { await _uow.RollbackAsync(ct); return null; } var row = new TenantConfig { TenantKey = key, Schema = string.IsNullOrWhiteSpace(request.Schema) ? null : request.Schema!.Trim(), ConnectionString = string.IsNullOrWhiteSpace(request.ConnectionString) ? null : request.ConnectionString!.Trim(), Mode = request.Mode, IsActive = request.IsActive, UpdatedAtUtc = DateTimeOffset.UtcNow }; var ok = await _repo.CreateAsync(row, ct); if (!ok) { await _uow.RollbackAsync(ct); return null; } await _uow.CommitAsync(ct); await _provisioner.ProvisionAsync(key, ct); return new CreateTenantResponse(key); } catch { await _uow.RollbackAsync(ct); throw; } } }