using EntKube.Identity.Domain;
using EntKube.SharedKernel.Domain;

namespace EntKube.Identity.Features.CreateTenant;

/// <summary>
/// Handles creation of a new tenant. When a user signs up or an admin creates
/// a new organization, this handler validates the request, ensures the slug is
/// unique, creates the tenant aggregate, and persists it. The creating user
/// becomes the first admin of the tenant.
/// </summary>
public class CreateTenantHandler
{
    private readonly ITenantRepository repository;

    public CreateTenantHandler(ITenantRepository repository)
    {
        this.repository = repository;
    }

    public async Task<Result<Guid>> HandleAsync(CreateTenantRequest request, CancellationToken ct = default)
    {
        // Validate required fields.

        if (string.IsNullOrWhiteSpace(request.Name))
        {
            return Result.Failure<Guid>("Tenant name is required.");
        }

        if (string.IsNullOrWhiteSpace(request.Slug))
        {
            return Result.Failure<Guid>("Tenant slug is required.");
        }

        if (request.CreatingUserId == Guid.Empty)
        {
            return Result.Failure<Guid>("Creating user ID is required.");
        }

        // Ensure no other tenant already uses this slug. Slugs are used in URLs
        // and must be globally unique across the platform.

        Tenant? existing = await repository.GetBySlugAsync(request.Slug.ToLowerInvariant(), ct);

        if (existing is not null)
        {
            return Result.Failure<Guid>($"A tenant with slug '{request.Slug}' already exists.");
        }

        // Create the tenant aggregate and persist it.

        Tenant tenant = Tenant.Create(request.Name, request.Slug, request.CreatingUserId);
        await repository.AddAsync(tenant, ct);

        return Result.Success(tenant.Id);
    }
}

public record CreateTenantRequest(string Name, string Slug, Guid CreatingUserId);
