using System.Globalization;
using System.Text.Json;

namespace Inspectron.Epson.Templates.Interpreter;

public class FormatResolver
{
    private readonly CultureInfo _culture;

    public FormatResolver(CultureInfo? culture = null)
    {
        _culture = culture ?? CultureInfo.InvariantCulture;
    }

    public string Format(JsonElement? element, string? format)
    {
        if (!element.HasValue || element.Value.ValueKind == JsonValueKind.Null)
        {
            return string.Empty;
        }

        var value = element.Value;

        if (string.IsNullOrEmpty(format))
        {
            return GetDefaultString(value);
        }

        return value.ValueKind switch
        {
            JsonValueKind.Number => FormatNumber(value, format),
            JsonValueKind.String => FormatString(value.GetString(), format),
            _ => GetDefaultString(value)
        };
    }

    private string FormatNumber(JsonElement value, string format)
    {
        // Try to get as decimal for precision
        if (value.TryGetDecimal(out var decimalValue))
        {
            try
            {
                return decimalValue.ToString(format, _culture);
            }
            catch (FormatException)
            {
                return decimalValue.ToString(_culture);
            }
        }

        if (value.TryGetDouble(out var doubleValue))
        {
            try
            {
                return doubleValue.ToString(format, _culture);
            }
            catch (FormatException)
            {
                return doubleValue.ToString(_culture);
            }
        }

        return value.GetRawText();
    }

    private string FormatString(string? value, string format)
    {
        if (string.IsNullOrEmpty(value))
        {
            return string.Empty;
        }

        // Try to parse as DateTime
        if (DateTime.TryParse(value, out var dateTime))
        {
            try
            {
                return dateTime.ToString(format, _culture);
            }
            catch (FormatException)
            {
                return value;
            }
        }

        // Try to parse as DateTimeOffset (for ISO 8601 strings)
        if (DateTimeOffset.TryParse(value, out var dateTimeOffset))
        {
            try
            {
                return dateTimeOffset.ToString(format, _culture);
            }
            catch (FormatException)
            {
                return value;
            }
        }

        // If it's a number in string form
        if (decimal.TryParse(value, out var decimalValue))
        {
            try
            {
                return decimalValue.ToString(format, _culture);
            }
            catch (FormatException)
            {
                return value;
            }
        }

        return value;
    }

    private string GetDefaultString(JsonElement value)
    {
        return value.ValueKind switch
        {
            JsonValueKind.String => value.GetString() ?? string.Empty,
            JsonValueKind.Number => value.GetRawText(),
            JsonValueKind.True => "true",
            JsonValueKind.False => "false",
            JsonValueKind.Null => string.Empty,
            JsonValueKind.Undefined => string.Empty,
            _ => value.GetRawText()
        };
    }
}
