using CompatApiClient.Utils;

namespace CompatBot.Utils;

internal static class EmbedPager
{
    public const int MaxTitleLength = 256;
    public const int MaxDescriptionLength = 4096;
    public const int MaxFields = 25;
    public const int MaxFieldTitleLength = 256;
    public const int MaxFieldLength = 1024;
    public const int MaxFooterLength = 2048;
    public const int MaxAuthorNameLength = 256;
    public const int MaxMessageLength = 2000;
    public const int MaxFollowupMessages = 5;

    public static IEnumerable<DiscordEmbed> BreakInEmbeds(this IEnumerable<string> lines, DiscordEmbedBuilder builder, int maxLinesPerField = 10, string? titleBase = null)
    {
        string getTitle(string autoGeneratedTitle, int count)
        {
            if (titleBase == null)
                return autoGeneratedTitle;
            return $"{titleBase} #{count}";
        }
        var fieldCount = 0;
        foreach (var field in BreakInFieldContent(lines, maxLinesPerField))
        {
            if (builder.Fields.Count == MaxFields)
            {
                yield return builder.Build();
                builder.ClearFields();
                fieldCount = 0;
            }
            var title = getTitle(field.title.ToUpperInvariant(), fieldCount).Trim(MaxFieldTitleLength);
            builder.AddField(title, field.content, true);
            fieldCount++;
        }
        if (builder.Fields.Count > 0)
            yield return builder.Build();
    }

    public static IEnumerable<(string title, string content)> BreakInFieldContent(this IEnumerable<string> lines, int maxLinesPerField = 10, Func<string?, string?, string>? makeTitle = null)
    {
        if (maxLinesPerField < 1)
            throw new ArgumentException("Expected a number greater than 0, but was " + maxLinesPerField, nameof(maxLinesPerField));

        makeTitle ??= MakeTitle;
        var buffer = new StringBuilder();
        var lineCount = 0;
        string? firstLine = null, lastLine = null;
        foreach (var line in lines)
        {
            if (string.IsNullOrEmpty(firstLine))
                firstLine = line;

            if (lineCount == maxLinesPerField)
            {
                yield return (makeTitle(firstLine, lastLine), buffer.ToString());
                buffer.Clear();
                lineCount = 0;
                firstLine = line;
            }

            if (buffer.Length + line.Length + Environment.NewLine.Length > MaxFieldLength)
            {
                if (buffer.Length + line.Length > MaxFieldLength)
                {
                    if (buffer.Length == 0)
                        yield return (makeTitle(line, line), line.Trim(MaxFieldLength));
                    else
                    {
                        yield return (makeTitle(firstLine, lastLine), buffer.ToString());
                        buffer.Clear().Append(line);
                        lineCount = 1;
                        firstLine = line;
                    }
                }
                else
                {
                    yield return (makeTitle(firstLine, line), buffer.Append(line).ToString());
                    buffer.Clear();
                    lineCount = 0;
                }
            }
            else
            {
                if (buffer.Length > 0)
                    buffer.AppendLine();
                buffer.Append(line);
                lineCount++;
                lastLine = line;
            }
        }
        if (buffer.Length > 0)
            yield return (makeTitle(firstLine, lastLine), buffer.ToString());
    }

    private static string MakeTitle(string? first, string? last)
    {
        if (string.IsNullOrEmpty(first) || string.IsNullOrEmpty(last))
            return first + last;

        if (first == last)
            return first[..1];

        if (last.StartsWith(first))
            return $"{first} - {last}";

        var commonPrefix = "";
        var maxPrefixSize = Math.Min(Math.Min(first.Length, last.Length), MaxFieldTitleLength/2);
        for (var i = 0; i < maxPrefixSize; i++)
        {
            if (first[i] == last[i])
                commonPrefix += first[i];
            else
                return $"{(commonPrefix + first[i]).TrimEnd()}-{(commonPrefix + last[i]).TrimEnd()}";
        }
        return commonPrefix;
    }
}