using Framework.DataType;

namespace Server.Infrastructure.TagHelpers;

public class ModelExpressionConverter : object
{
    public ModelExpressionConverter
        (Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExpression modelExpression)
    {
        IsLeftToRight = false;
        HasBeenConverted = false;
        ModelExpression = modelExpression;

        if (modelExpression.ModelExplorer.ModelType.IsEnum)
        {
            ConvertLong();
        }
        else
        {
            switch (modelExpression.ModelExplorer.ModelType)
            {
                case Type typeGuid when typeGuid == typeof(Guid):
                    {
                        ConvertGuid();

                        break;
                    }

                case Type typeInt when typeInt == typeof(int):
                case Type typeByte when typeByte == typeof(byte):
                case Type typeLong when typeLong == typeof(long):
                    {
                        ConvertLong();

                        break;
                    }

                case Type typeDateTime when typeDateTime == typeof(DateTime):
                    {
                        ConvertDateTime();

                        break;
                    }

                case Type typeDateTimeOffset when typeDateTimeOffset == typeof(DateTimeOffset):
                case Type typeDateTimeOffsetOrNull when typeDateTimeOffsetOrNull == typeof(DateTimeOffset?):
                    {
                        ConvertDateTimeOffset();

                        break;
                    }
            }
        }
    }

    public string? Value { get; protected set; }

    public bool IsLeftToRight { get; protected set; }

    public bool HasBeenConverted { get; protected set; }

    protected Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExpression ModelExpression { get; }

    protected void ConvertGuid()
    {
        object value =
            ModelExpression.Model;

        IsLeftToRight = true;
        HasBeenConverted = true;

        if (value is null)
        {
            Value = Constants.Format.NullValue;
            return;
        }

        Value = value.ToString();
    }

    protected void ConvertLong()
    {
        object value =
            ModelExpression.Model;

        IsLeftToRight = true;
        HasBeenConverted = true;

        if (value is null)
        {
            Value = Constants.Format.NullValue;
            return;
        }

        var valueInteget =
            Convert.ToInt64(value: value);

        var result =
            valueInteget.ToString
            (format: Constants.Format.Integer);

        result = result
            .ConvertDigitsToUnicode();

        if (result is null)
        {
            Value = Constants.Format.NullValue;
            return;
        }

        Value = result;
    }

    protected void ConvertDateTime()
    {
        object value =
            ModelExpression.Model;

        IsLeftToRight = true;
        HasBeenConverted = true;

        if (value is null)
        {
            Value = Constants.Format.NullValue;
            return;
        }

        var valueDateTime =
            (DateTime)value;

        var result =
            valueDateTime.ToString
            (format: Constants.Format.DateTime);

        result = result
            .ConvertDigitsToUnicode();

        if (result is null)
        {
            Value = Constants.Format.NullValue;
            return;
        }

        Value = result;
    }

    protected void ConvertDateTimeOffset()
    {
        object value =
            ModelExpression.Model;

        IsLeftToRight = true;
        HasBeenConverted = true;

        if (value is null)
        {
            Value = Constants.Format.NullValue;
            return;
        }

        var valueDateTime =
            (DateTimeOffset)value;

        var result =
            valueDateTime.DateTime.ToString
            (format: Constants.Format.DateTime);

        result = result
            .ConvertDigitsToUnicode();

        if (result is null)
        {
            Value = Constants.Format.NullValue;
            return;
        }

        Value = result;
    }
}
