namespace RobotNet.WebApp.Scripts.Models;

public class ScriptValueModel(string name, string type, string valueDefault)
{
    private static readonly Dictionary<string, Type> predefinedMap = new()
    {
        ["System.Boolean"] = typeof(bool),
        ["System.Byte"] = typeof(byte),
        ["System.SByte"] = typeof(sbyte),
        ["System.Int16"] = typeof(short),
        ["System.UInt16"] = typeof(ushort),
        ["System.Int32"] = typeof(int),
        ["System.UInt32"] = typeof(uint),
        ["System.Int64"] = typeof(long),
        ["System.UInt64"] = typeof(ulong),
        ["System.Single"] = typeof(float),
        ["System.Double"] = typeof(double),
        ["System.Decimal"] = typeof(decimal),
        ["System.Char"] = typeof(char),
        ["System.String"] = typeof(string)
    };

    public string Name { get; } = name;
    public string Type { get; } = type;
    public string? Default { get; } = valueDefault;

    public object? Value { get; set; } = null;

    private void EnsureType(string expectedType)
    {
        if (Type != expectedType)
            throw new InvalidOperationException($"Parameter '{Name}' is not of type '{expectedType}'. Actual type: '{Type}'.");
    }

    public override string ToString()
    {
        return Value?.ToString() ?? "null";
    }

    public bool BoolValue
    {
        get
        {
            EnsureType("System.Boolean");
            return Value is not null && (bool)Value;
        }
        set
        {
            EnsureType("System.Boolean");
            Value = value;
        }
    }

    public byte ByteValue
    {
        get
        {
            EnsureType("System.Byte");
            return Value is null ? default : (byte)Value;
        }
        set
        {
            EnsureType("System.Byte");
            Value = value;
        }
    }

    public sbyte SByteValue
    {
        get
        {
            EnsureType("System.SByte");
            return Value is null ? default : (sbyte)Value;
        }
        set
        {
            EnsureType("System.SByte");
            Value = value;
        }
    }

    public short ShortValue
    {
        get
        {
            EnsureType("System.Int16");
            return Value is null ? default : (short)Value;
        }
        set
        {
            EnsureType("System.Int16");
            Value = value;
        }
    }

    public ushort UShortValue
    {
        get
        {
            EnsureType("System.UInt16");
            return Value is null ? default : (ushort)Value;
        }
        set
        {
            EnsureType("System.UInt16");
            Value = value;
        }
    }

    public int IntValue
    {
        get
        {
            EnsureType("System.Int32");
            return Value is null ? default : (int)Value;
        }
        set
        {
            EnsureType("System.Int32");
            Value = value;
        }
    }

    public uint UIntValue
    {
        get
        {
            EnsureType("System.UInt32");
            return Value is null ? default : (uint)Value;
        }
        set
        {
            EnsureType("System.UInt32");
            Value = value;
        }
    }

    public long LongValue
    {
        get
        {
            EnsureType("System.Int64");
            return Value is null ? default : (long)Value;
        }
        set
        {
            EnsureType("System.Int64");
            Value = value;
        }
    }

    public ulong ULongValue
    {
        get
        {
            EnsureType("System.UInt64");
            return Value is null ? default : (ulong)Value;
        }
        set
        {
            EnsureType("System.UInt64");
            Value = value;
        }
    }

    public float FloatValue
    {
        get
        {
            EnsureType("System.Single");
            return Value is null ? default : (float)Value;
        }
        set
        {
            EnsureType("System.Single");
            Value = value;
        }
    }

    public double DoubleValue
    {
        get
        {
            EnsureType("System.Double");
            return Value is null ? default : (double)Value;
        }
        set
        {
            EnsureType("System.Double");
            Value = value;
        }
    }

    public decimal DecimalValue
    {
        get
        {
            EnsureType("System.Decimal");
            return Value is null ? default : (decimal)Value;
        }
        set
        {
            EnsureType("System.Decimal");
            Value = value;
        }
    }

    public char CharValue
    {
        get
        {
            EnsureType("System.Char");
            return Value is null ? default : (char)Value;
        }
        set
        {
            EnsureType("System.Char");
            Value = value;
        }
    }

    public string StringValue
    {
        get
        {
            EnsureType("System.String");
            return Value is null ? string.Empty : (string)Value;
        }
        set
        {
            EnsureType("System.String");
            Value = value;
        }
    }

    public void Reset()
    {
        if (predefinedMap.TryGetValue(Type, out var type))
        {
            Value = type.IsValueType ? Activator.CreateInstance(type) : (type == typeof(string) ? string.Empty : null);
        }
        else
        {
            Value = null;
        }
    }
}
