using IWS5.Core.Enums;
using IWS5.Core.Models.Request;

namespace IWS5.Core.Helpers;

public static class TypeHelpers
{
    public static Type GetClrType(ATDocumentFieldType? fieldType)
    {
        return fieldType switch
        {
            ATDocumentFieldType.Boolean => typeof(bool),
            ATDocumentFieldType.Integer => typeof(int),
            ATDocumentFieldType.Number => typeof(decimal),
            ATDocumentFieldType.String => typeof(string),
            ATDocumentFieldType.Date => typeof(DateTime),
            _ => typeof(string)
        };
    }
    
    public static string GetSqlType(ATDocumentFieldType fieldInstanceType, int? size = null)
    {
        return fieldInstanceType switch
        {
            ATDocumentFieldType.Boolean => "BIT",
            ATDocumentFieldType.Integer => "INT",
            ATDocumentFieldType.Number => "DECIMAL(28, 14)",
            ATDocumentFieldType.String => size != null ? $"NVARCHAR({size})" : "NVARCHAR(255)",
            ATDocumentFieldType.Date => "DateTime",
            _ => "NVARCHAR(MAX)"
        };
    }
    
    public static bool IsParsable(ATDocumentFieldType fieldInstanceType, string fieldValue)
    {
        try
        {
            return fieldInstanceType switch
            {
                ATDocumentFieldType.String => true,
                ATDocumentFieldType.Boolean => bool.TryParse(fieldValue, out _) || fieldValue == "0" || fieldValue == "1",
                ATDocumentFieldType.Integer => int.TryParse(fieldValue, out _),
                ATDocumentFieldType.Number => decimal.TryParse(fieldValue, out _),
                ATDocumentFieldType.Date => DateTime.TryParse(fieldValue, out _),
                _ => false
            };
        }
        catch
        {
            return false;
        }
    }
    
    public static object? ParseValue(ATDocumentFieldType fieldType, string fieldValue)
    {
        if (string.IsNullOrEmpty(fieldValue))
            return null;

        var clrType = GetClrType(fieldType);

        try
        {
            return clrType switch
            {
                Type t when t == typeof(bool) => ParseBooleanValue(fieldValue),
                Type t when t == typeof(int) => int.Parse(fieldValue),
                Type t when t == typeof(decimal) => decimal.Parse(fieldValue),
                Type t when t == typeof(DateTime) => DateTime.Parse(fieldValue),
                Type t when t == typeof(string) => fieldValue,
                _ => throw new InvalidOperationException($"Unsupported field type: {fieldType}")
            };
        }
        catch (FormatException ex)
        {
            throw new FormatException($"Failed to parse '{fieldValue}' to {clrType.Name}", ex);
        }
    }
    
    private static bool ParseBooleanValue(string value)
    {
        var parsed = bool.TryParse(value, out var result);
        if (parsed)
            return result;

        var paredAsNumber = int.TryParse(value, out var intValue);
        if (paredAsNumber) 
            return intValue == 1;

        return false;

    }
}