namespace CashLineERP.Application.Integration;

public static class IntegrationEndpointRegistryCatalog
{
    private static readonly string[] SupportedProviderCodes =
    [
        "DOCUMENT",
        "ETA",
        "FAWRY",
        "FX_SOURCE",
        "NOTIFICATION",
        "PAYMOB"
    ];

    private static readonly string[] SupportedEnvironmentCodes =
    [
        "CERT",
        "DEV",
        "TEST",
        "SIT",
        "UAT",
        "PROD"
    ];

    private static readonly string[] SupportedDirectionCodes =
    [
        "INBOUND",
        "OUTBOUND"
    ];

    private static readonly string[] SupportedTransportCodes =
    [
        "REST",
        "WEBHOOK"
    ];

    private static readonly string[] SupportedHttpMethodCodes =
    [
        "DELETE",
        "GET",
        "PATCH",
        "POST",
        "PUT"
    ];

    private static readonly string[] SupportedAuthenticationModeCodes =
    [
        "API_KEY",
        "BASIC",
        "BEARER",
        "MTLS",
        "NONE",
        "SIGNATURE"
    ];

    private static readonly string[] SupportedRetryPolicyCodes =
    [
        "AGGRESSIVE",
        "MANUAL_REVIEW",
        "NONE",
        "STANDARD"
    ];

    public static string NormalizeProviderCode(string integrationProviderCode) =>
        NormalizeRequiredCode(integrationProviderCode, SupportedProviderCodes, "integration provider");

    public static string NormalizeEnvironmentCode(string environmentCode) =>
        NormalizeRequiredCode(environmentCode, SupportedEnvironmentCodes, "environment");

    public static string NormalizeDirectionCode(string directionCode) =>
        NormalizeRequiredCode(directionCode, SupportedDirectionCodes, "direction");

    public static string NormalizeTransportCode(string transportCode) =>
        NormalizeRequiredCode(transportCode, SupportedTransportCodes, "transport");

    public static string NormalizeHttpMethodCode(string httpMethodCode) =>
        NormalizeRequiredCode(httpMethodCode, SupportedHttpMethodCodes, "HTTP method");

    public static string NormalizeAuthenticationModeCode(string authenticationModeCode) =>
        NormalizeRequiredCode(authenticationModeCode, SupportedAuthenticationModeCodes, "authentication mode");

    public static string NormalizeRetryPolicyCode(string retryPolicyCode) =>
        NormalizeRequiredCode(retryPolicyCode, SupportedRetryPolicyCodes, "retry policy");

    public static string NormalizeBaseUrl(string baseUrl)
    {
        var normalized = baseUrl?.Trim();
        if (string.IsNullOrWhiteSpace(normalized))
        {
            throw new InvalidOperationException("Integration endpoint base URL is required.");
        }

        if (!Uri.TryCreate(normalized, UriKind.Absolute, out var parsedUri)
            || (parsedUri.Scheme != Uri.UriSchemeHttp && parsedUri.Scheme != Uri.UriSchemeHttps))
        {
            throw new InvalidOperationException("Integration endpoint base URL must be a valid HTTP or HTTPS URI.");
        }

        if (!string.IsNullOrWhiteSpace(parsedUri.AbsolutePath) && parsedUri.AbsolutePath != "/")
        {
            throw new InvalidOperationException("Integration endpoint base URL must not include a path segment. Use relative path instead.");
        }

        return parsedUri.GetLeftPart(UriPartial.Authority);
    }

    public static string? NormalizeRelativePath(string? relativePath)
    {
        if (string.IsNullOrWhiteSpace(relativePath))
        {
            return null;
        }

        var normalized = relativePath.Trim();
        if (!normalized.StartsWith('/'))
        {
            normalized = "/" + normalized;
        }

        return normalized;
    }

    public static string? NormalizeCredentialReference(string? credentialReference) =>
        string.IsNullOrWhiteSpace(credentialReference) ? null : credentialReference.Trim();

    public static string NormalizeEndpointName(string endpointName)
    {
        var normalized = endpointName?.Trim();
        if (string.IsNullOrWhiteSpace(normalized))
        {
            throw new InvalidOperationException("Integration endpoint name is required.");
        }

        return normalized;
    }

    public static void ValidateOperationalSettings(
        string transportCode,
        string httpMethodCode,
        int timeoutSeconds,
        int maxRetryCount)
    {
        if (!string.Equals(transportCode, "REST", StringComparison.OrdinalIgnoreCase)
            && !string.Equals(transportCode, "WEBHOOK", StringComparison.OrdinalIgnoreCase))
        {
            throw new InvalidOperationException("Only REST and WEBHOOK transports are supported in the current integration registry baseline.");
        }

        NormalizeHttpMethodCode(httpMethodCode);

        if (timeoutSeconds is < 5 or > 300)
        {
            throw new InvalidOperationException("Integration endpoint timeout must be between 5 and 300 seconds.");
        }

        if (maxRetryCount is < 0 or > 10)
        {
            throw new InvalidOperationException("Integration endpoint retry count must be between 0 and 10.");
        }
    }

    private static string NormalizeRequiredCode(string value, IReadOnlyCollection<string> supportedValues, string label)
    {
        var normalized = value?.Trim().ToUpperInvariant();
        if (string.IsNullOrWhiteSpace(normalized))
        {
            throw new InvalidOperationException($"Integration endpoint {label} code is required.");
        }

        if (!supportedValues.Contains(normalized))
        {
            throw new InvalidOperationException($"Integration endpoint {label} code '{normalized}' is not supported by the current registry baseline.");
        }

        return normalized;
    }
}
