using System.Text.Json;

namespace Inspectron.PrintServer.TemplateEditor.Services;

public record JsonPropertyInfo(string Path, string Type, bool IsArray);

public static class JsonPathExtractor
{
    public static List<JsonPropertyInfo> Extract(string json)
    {
        var results = new List<JsonPropertyInfo>();

        try
        {
            using var doc = JsonDocument.Parse(json);
            WalkElement(doc.RootElement, "", results);
        }
        catch (JsonException)
        {
            // Invalid JSON - return empty list
        }

        return results;
    }

    private static void WalkElement(JsonElement element, string prefix, List<JsonPropertyInfo> results)
    {
        switch (element.ValueKind)
        {
            case JsonValueKind.Object:
                foreach (var prop in element.EnumerateObject())
                {
                    var path = string.IsNullOrEmpty(prefix) ? prop.Name : $"{prefix}.{prop.Name}";

                    var type = GetTypeName(prop.Value.ValueKind);
                    var isArray = prop.Value.ValueKind == JsonValueKind.Array;

                    results.Add(new JsonPropertyInfo(path, type, isArray));

                    if (prop.Value.ValueKind == JsonValueKind.Object)
                    {
                        WalkElement(prop.Value, path, results);
                    }
                    else if (prop.Value.ValueKind == JsonValueKind.Array)
                    {
                        WalkArrayElement(prop.Value, path, results);
                    }
                }
                break;
        }
    }

    private static void WalkArrayElement(JsonElement array, string arrayPath, List<JsonPropertyInfo> results)
    {
        // Inspect first element to discover item property paths
        foreach (var item in array.EnumerateArray())
        {
            if (item.ValueKind == JsonValueKind.Object)
            {
                // Use "[item]" prefix to indicate these are array item properties
                foreach (var prop in item.EnumerateObject())
                {
                    var itemPath = $"{arrayPath}[].{prop.Name}";
                    var type = GetTypeName(prop.Value.ValueKind);
                    var isArray = prop.Value.ValueKind == JsonValueKind.Array;

                    results.Add(new JsonPropertyInfo(itemPath, type, isArray));

                    if (prop.Value.ValueKind == JsonValueKind.Object)
                    {
                        WalkElement(prop.Value, itemPath, results);
                    }
                    else if (prop.Value.ValueKind == JsonValueKind.Array)
                    {
                        WalkArrayElement(prop.Value, itemPath, results);
                    }
                }
            }

            break; // Only inspect the first element
        }
    }

    private static string GetTypeName(JsonValueKind kind) => kind switch
    {
        JsonValueKind.String => "string",
        JsonValueKind.Number => "number",
        JsonValueKind.True or JsonValueKind.False => "boolean",
        JsonValueKind.Array => "array",
        JsonValueKind.Object => "object",
        JsonValueKind.Null => "null",
        _ => "unknown"
    };
}
