using ApiOPE.Services;

namespace ApiOPE.Configuration;

public sealed class OpeOptions
{
    public const string SectionName = "Ope";

    public string Version { get; set; } = "1.0";

    public string ClientToken { get; set; } = string.Empty;

    public string SecretKey { get; set; } = string.Empty;

    public string PublicBaseUrl { get; set; } = string.Empty;

    public int TokenMaxAgeSeconds { get; set; } = 300;

    public int ClockSkewSeconds { get; set; } = 60;

    public string OrganizationId { get; set; } = string.Empty;

    public string OrganizationDir3 { get; set; } = string.Empty;

    public string OrganizationCif { get; set; } = string.Empty;

    public List<string> OutputFields { get; set; } = [];
}

public static class OpeOptionsValidator
{
    public static bool IsValid(OpeOptions options, bool isDevelopment)
    {
        if (!string.Equals(options.Version, "1.0", StringComparison.Ordinal) ||
            string.IsNullOrWhiteSpace(options.ClientToken) ||
            string.IsNullOrWhiteSpace(options.SecretKey) ||
            options.SecretKey.Length < 32 ||
            string.IsNullOrWhiteSpace(options.OrganizationId) ||
            string.IsNullOrWhiteSpace(options.OrganizationDir3) ||
            string.IsNullOrWhiteSpace(options.OrganizationCif) ||
            options.TokenMaxAgeSeconds is < 1 or > 900 ||
            options.ClockSkewSeconds is < 0 or > 300 ||
            options.OutputFields is null ||
            options.OutputFields.Count is < 1 or > 10 ||
            options.OutputFields.Distinct(StringComparer.Ordinal).Count() != options.OutputFields.Count ||
            options.OutputFields.Any(field => !OpeFieldMapper.SupportedInternalFields.Contains(field)))
        {
            return false;
        }

        if (!Uri.TryCreate(options.PublicBaseUrl, UriKind.Absolute, out var publicBaseUri) ||
            (publicBaseUri.Scheme != Uri.UriSchemeHttps && publicBaseUri.Scheme != Uri.UriSchemeHttp) ||
            !string.IsNullOrEmpty(publicBaseUri.UserInfo) ||
            !string.IsNullOrEmpty(publicBaseUri.Query) ||
            !string.IsNullOrEmpty(publicBaseUri.Fragment))
        {
            return false;
        }

        return isDevelopment || publicBaseUri.Scheme == Uri.UriSchemeHttps;
    }
}
