using System.Text;
using System.Text.RegularExpressions;

namespace NexusReader.Infrastructure.Helpers;

public static class JsonRepairHelper
{
    public static string Repair(string json)
    {
        if (string.IsNullOrWhiteSpace(json)) return json;
        json = json.Trim();

        // 1. If it doesn't end with } or ], it's definitely truncated
        if (!json.EndsWith("}") && !json.EndsWith("]"))
        {
            // Try to find the last "clean" closing point before the truncation
            // We look for a comma, a closing brace, or a closing bracket that is followed by noise
            int lastGoodComma = json.LastIndexOf(',');
            int lastGoodBrace = json.LastIndexOf('}');
            int lastGoodBracket = json.LastIndexOf(']');

            int cutoff = Math.Max(lastGoodComma, Math.Max(lastGoodBrace, lastGoodBracket));
            
            if (cutoff > 0)
            {
                // Prune the "garbage" at the end
                json = json.Substring(0, cutoff);
            }
            
            // Now apply the standard stack-based closing logic
            var stack = new Stack<char>();
            bool inString = false;
            bool escaped = false;

            foreach (char c in json)
            {
                if (escaped) { escaped = false; continue; }
                if (c == '\\') { escaped = true; continue; }
                if (c == '"') { inString = !inString; continue; }
                if (inString) continue;

                if (c == '{' || c == '[') stack.Push(c);
                else if (c == '}' || c == ']')
                {
                    if (stack.Count > 0)
                    {
                        var last = stack.Peek();
                        if ((c == '}' && last == '{') || (c == ']' && last == '['))
                            stack.Pop();
                    }
                }
            }

            var builder = new StringBuilder(json);
            if (inString) builder.Append('"');

            while (stack.Count > 0)
            {
                var c = stack.Pop();
                if (c == '{') builder.Append("}");
                else if (c == '[') builder.Append("]");
            }
            
            return builder.ToString();
        }

        return json;
    }
}
