using System.Globalization;
using System.Security.Cryptography;
using Microsoft.IdentityModel.Tokens;
using Tiku.Domain.Tenancy;

namespace Tiku.Infrastructure.Tenancy;

internal static class TenantDomainProvisioning
{
    public static TenantDomain CreatePrimary(Guid tenantId, string host)
    {
        return new TenantDomain
        {
            TenantId = tenantId,
            Host = NormalizeHost(host),
            DomainType = TenantDomainType.Custom,
            Status = TenantDomainStatus.Pending,
            IsPrimary = true,
            VerificationToken = Base64UrlEncoder.Encode(RandomNumberGenerator.GetBytes(32))
        };
    }

    public static string NormalizeHost(string value)
    {
        var candidate = value.Trim().TrimEnd('.');
        if (candidate.Length == 0 || candidate.Contains('/') || candidate.Contains(':') || candidate.Contains('*'))
            throw new ArgumentException("A DNS host without scheme, port, path or wildcard is required.",
                nameof(value));

        string ascii;
        try
        {
            ascii = new IdnMapping().GetAscii(candidate).ToLowerInvariant();
        }
        catch (ArgumentException)
        {
            throw new ArgumentException("The domain host is invalid.", nameof(value));
        }

        if (ascii.Length > 253 || ascii.Split('.').Length < 2 ||
            ascii.Split('.').Any(label => label.Length is 0 or > 63 ||
                                          label.StartsWith('-') || label.EndsWith('-') ||
                                          label.Any(character =>
                                              !char.IsAsciiLetterOrDigit(character) && character != '-')))
            throw new ArgumentException("The domain host is invalid.", nameof(value));

        return ascii;
    }
}