using System.Reflection;
using System.Text.Json;
using Kbx.Contracts.Generated;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace Kbx.Contracts;

/// <summary>
/// Adds non-business KBX field metadata to OpenAPI properties.
/// Domain validation rules are intentionally not emitted from the field dictionary.
/// </summary>
public sealed class KbxFieldOpenApiSchemaFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        foreach (var property in context.Type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
        {
            var attribute = property.GetCustomAttribute<KbxFieldKeyAttribute>();
            if (attribute is null || !KbxFieldCatalog.TryGet(attribute.FieldKey, out var field) || field is null)
                continue;

            var jsonName = JsonNamingPolicy.CamelCase.ConvertName(property.Name);
            if (!schema.Properties.TryGetValue(jsonName, out var propertySchema))
            {
                var match = schema.Properties.FirstOrDefault(x => string.Equals(x.Key, property.Name, StringComparison.OrdinalIgnoreCase));
                propertySchema = match.Value;
            }
            if (propertySchema is null) continue;

            propertySchema.Extensions["x-kbx-field-key"] = new OpenApiString(field.Key);
            propertySchema.Extensions["x-kbx-field-label"] = new OpenApiString(field.Label);
            propertySchema.Extensions["x-kbx-sensitive"] = new OpenApiBoolean(field.Sensitive);
            if (!string.IsNullOrWhiteSpace(field.Masking))
                propertySchema.Extensions["x-kbx-masking"] = new OpenApiString(field.Masking);
        }
    }
}
