using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AS400API.Infrastructure;

public static class DatabaseRowFormatter
{
    public static IEnumerable<IDictionary<string, object?>> ToCamelCaseDictionaries(this IEnumerable<dynamic> rows)
    {
        foreach (var row in rows)
        {
            if (row is IDictionary<string, object> dict)
            {
                yield return dict.ToCamelCaseDictionary();
            }
            else
            {
                yield return new Dictionary<string, object?>
                {
                    ["value"] = row
                };
            }
        }
    }

    public static IDictionary<string, object?> ToCamelCaseDictionary(this IDictionary<string, object> source)
    {
        var result = new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase);
        foreach (var kvp in source)
        {
            var key = string.IsNullOrWhiteSpace(kvp.Key) ? kvp.Key : ToCamelCase(kvp.Key);
            result[key] = kvp.Value;
        }

        return result;
    }

    private static string ToCamelCase(string input)
    {
        if (string.IsNullOrEmpty(input))
        {
            return input;
        }

        var segments = input
            .Split(new[] { '_', ' ', '-' }, StringSplitOptions.RemoveEmptyEntries)
            .Select(s => s.ToLowerInvariant())
            .ToArray();

        if (segments.Length == 0)
        {
            return input;
        }

        if (segments.Length == 1)
        {
            var segment = segments[0];
            if (segment.Length == 1)
            {
                return segment.ToLowerInvariant();
            }

            return char.ToLowerInvariant(segment[0]) + segment[1..];
        }

        var sb = new StringBuilder();
        sb.Append(segments[0]);
        for (var i = 1; i < segments.Length; i++)
        {
            var segment = segments[i];
            if (segment.Length == 0)
            {
                continue;
            }

            sb.Append(char.ToUpperInvariant(segment[0]));
            if (segment.Length > 1)
            {
                sb.Append(segment[1..]);
            }
        }

        return sb.ToString();
    }
}
