using System.Text.Json;
using System.Text.Json.Serialization;
using Meezi.Core.Discover;

namespace Meezi.Infrastructure.Discover;

public static class CafeDiscoverProfileSerializer
{
    private static readonly JsonSerializerOptions JsonOptions = new()
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
        DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
        PropertyNameCaseInsensitive = true
    };

    public static CafeDiscoverProfile Deserialize(string? json)
    {
        if (string.IsNullOrWhiteSpace(json))
            return new CafeDiscoverProfile();

        try
        {
            var profile = JsonSerializer.Deserialize<CafeDiscoverProfile>(json, JsonOptions);
            return Sanitize(profile ?? new CafeDiscoverProfile());
        }
        catch
        {
            return new CafeDiscoverProfile();
        }
    }

    public static string Serialize(CafeDiscoverProfile profile) =>
        JsonSerializer.Serialize(Sanitize(profile), JsonOptions);

    public static CafeDiscoverProfile Sanitize(CafeDiscoverProfile input)
    {
        var p = new CafeDiscoverProfile
        {
            Size = NormalizeSingle(input.Size, CafeDiscoverProfileKeys.Sizes),
            Floors = NormalizeSingle(input.Floors, CafeDiscoverProfileKeys.Floors),
            NoiseLevel = NormalizeSingle(input.NoiseLevel, CafeDiscoverProfileKeys.NoiseLevels),
            PriceTier = NormalizeSingle(input.PriceTier, CafeDiscoverProfileKeys.PriceTiers),
            Themes = NormalizeList(input.Themes, CafeDiscoverProfileKeys.Themes),
            Vibes = NormalizeList(input.Vibes, CafeDiscoverProfileKeys.Vibes),
            Occasions = NormalizeList(input.Occasions, CafeDiscoverProfileKeys.Occasions),
            SpaceFeatures = NormalizeList(input.SpaceFeatures, CafeDiscoverProfileKeys.SpaceFeatures)
        };
        return p;
    }

    private static string? NormalizeSingle(string? value, HashSet<string> allowed)
    {
        if (string.IsNullOrWhiteSpace(value)) return null;
        var id = value.Trim().ToLowerInvariant();
        return allowed.Contains(id) ? id : null;
    }

    private static List<string> NormalizeList(IEnumerable<string>? values, HashSet<string> allowed)
    {
        if (values is null) return [];
        return values
            .Select(v => v.Trim().ToLowerInvariant())
            .Where(v => !string.IsNullOrEmpty(v) && allowed.Contains(v))
            .Distinct()
            .ToList();
    }
}
