using System.Text.Json;
using ColaFlow.Modules.Mcp.Domain.Exceptions;

namespace ColaFlow.Modules.Mcp.Application.Tools.Validation;

/// <summary>
/// Helper class for parsing and validating tool parameters
/// </summary>
public static class ToolParameterParser
{
    /// <summary>
    /// Parse a required string parameter
    /// </summary>
    public static string ParseString(Dictionary<string, object> args, string paramName, bool required = false)
    {
        if (!args.TryGetValue(paramName, out var value))
        {
            if (required)
                throw new McpInvalidParamsException($"Required parameter '{paramName}' is missing");
            return string.Empty;
        }

        if (value == null)
        {
            if (required)
                throw new McpInvalidParamsException($"Required parameter '{paramName}' cannot be null");
            return string.Empty;
        }

        // Handle JsonElement (from JSON deserialization)
        if (value is JsonElement jsonElement)
        {
            if (jsonElement.ValueKind == JsonValueKind.String)
                return jsonElement.GetString() ?? string.Empty;

            if (jsonElement.ValueKind == JsonValueKind.Null && required)
                throw new McpInvalidParamsException($"Required parameter '{paramName}' cannot be null");

            return jsonElement.ToString();
        }

        return value.ToString() ?? string.Empty;
    }

    /// <summary>
    /// Parse a required Guid parameter
    /// </summary>
    public static Guid? ParseGuid(Dictionary<string, object> args, string paramName, bool required = false)
    {
        if (!args.TryGetValue(paramName, out var value))
        {
            if (required)
                throw new McpInvalidParamsException($"Required parameter '{paramName}' is missing");
            return null;
        }

        if (value == null)
        {
            if (required)
                throw new McpInvalidParamsException($"Required parameter '{paramName}' cannot be null");
            return null;
        }

        // Handle JsonElement
        if (value is JsonElement jsonElement)
        {
            if (jsonElement.ValueKind == JsonValueKind.String)
            {
                var strValue = jsonElement.GetString();
                if (string.IsNullOrWhiteSpace(strValue))
                {
                    if (required)
                        throw new McpInvalidParamsException($"Required parameter '{paramName}' cannot be empty");
                    return null;
                }

                if (Guid.TryParse(strValue, out var guid))
                    return guid;

                throw new McpInvalidParamsException($"Parameter '{paramName}' must be a valid UUID");
            }

            if (jsonElement.ValueKind == JsonValueKind.Null && required)
                throw new McpInvalidParamsException($"Required parameter '{paramName}' cannot be null");
        }

        // Handle string
        var stringValue = value.ToString();
        if (string.IsNullOrWhiteSpace(stringValue))
        {
            if (required)
                throw new McpInvalidParamsException($"Required parameter '{paramName}' cannot be empty");
            return null;
        }

        if (Guid.TryParse(stringValue, out var result))
            return result;

        throw new McpInvalidParamsException($"Parameter '{paramName}' must be a valid UUID");
    }

    /// <summary>
    /// Parse an enum parameter
    /// </summary>
    public static TEnum? ParseEnum<TEnum>(Dictionary<string, object> args, string paramName, bool required = false)
        where TEnum : struct, Enum
    {
        if (!args.TryGetValue(paramName, out var value))
        {
            if (required)
                throw new McpInvalidParamsException($"Required parameter '{paramName}' is missing");
            return null;
        }

        if (value == null)
        {
            if (required)
                throw new McpInvalidParamsException($"Required parameter '{paramName}' cannot be null");
            return null;
        }

        // Handle JsonElement
        if (value is JsonElement jsonElement)
        {
            if (jsonElement.ValueKind == JsonValueKind.String)
            {
                var strValue = jsonElement.GetString();
                if (string.IsNullOrWhiteSpace(strValue))
                {
                    if (required)
                        throw new McpInvalidParamsException($"Required parameter '{paramName}' cannot be empty");
                    return null;
                }

                if (Enum.TryParse<TEnum>(strValue, ignoreCase: true, out var enumValue))
                    return enumValue;

                var validValues = string.Join(", ", Enum.GetNames<TEnum>());
                throw new McpInvalidParamsException(
                    $"Parameter '{paramName}' must be one of: {validValues}");
            }

            if (jsonElement.ValueKind == JsonValueKind.Null && required)
                throw new McpInvalidParamsException($"Required parameter '{paramName}' cannot be null");
        }

        // Handle string
        var stringValue = value.ToString();
        if (string.IsNullOrWhiteSpace(stringValue))
        {
            if (required)
                throw new McpInvalidParamsException($"Required parameter '{paramName}' cannot be empty");
            return null;
        }

        if (Enum.TryParse<TEnum>(stringValue, ignoreCase: true, out var result))
            return result;

        var validValuesList = string.Join(", ", Enum.GetNames<TEnum>());
        throw new McpInvalidParamsException(
            $"Parameter '{paramName}' must be one of: {validValuesList}");
    }

    /// <summary>
    /// Parse a decimal parameter
    /// </summary>
    public static decimal? ParseDecimal(Dictionary<string, object> args, string paramName, bool required = false)
    {
        if (!args.TryGetValue(paramName, out var value))
        {
            if (required)
                throw new McpInvalidParamsException($"Required parameter '{paramName}' is missing");
            return null;
        }

        if (value == null)
        {
            if (required)
                throw new McpInvalidParamsException($"Required parameter '{paramName}' cannot be null");
            return null;
        }

        // Handle JsonElement
        if (value is JsonElement jsonElement)
        {
            if (jsonElement.ValueKind == JsonValueKind.Number)
                return jsonElement.GetDecimal();

            if (jsonElement.ValueKind == JsonValueKind.String)
            {
                var strValue = jsonElement.GetString();
                if (string.IsNullOrWhiteSpace(strValue))
                {
                    if (required)
                        throw new McpInvalidParamsException($"Required parameter '{paramName}' cannot be empty");
                    return null;
                }

                if (decimal.TryParse(strValue, out var decimalValue))
                    return decimalValue;

                throw new McpInvalidParamsException($"Parameter '{paramName}' must be a valid number");
            }

            if (jsonElement.ValueKind == JsonValueKind.Null && required)
                throw new McpInvalidParamsException($"Required parameter '{paramName}' cannot be null");
        }

        // Try to convert directly
        try
        {
            return Convert.ToDecimal(value);
        }
        catch
        {
            throw new McpInvalidParamsException($"Parameter '{paramName}' must be a valid number");
        }
    }

    /// <summary>
    /// Parse an integer parameter
    /// </summary>
    public static int? ParseInt(Dictionary<string, object> args, string paramName, bool required = false)
    {
        if (!args.TryGetValue(paramName, out var value))
        {
            if (required)
                throw new McpInvalidParamsException($"Required parameter '{paramName}' is missing");
            return null;
        }

        if (value == null)
        {
            if (required)
                throw new McpInvalidParamsException($"Required parameter '{paramName}' cannot be null");
            return null;
        }

        // Handle JsonElement
        if (value is JsonElement jsonElement)
        {
            if (jsonElement.ValueKind == JsonValueKind.Number)
                return jsonElement.GetInt32();

            if (jsonElement.ValueKind == JsonValueKind.String)
            {
                var strValue = jsonElement.GetString();
                if (string.IsNullOrWhiteSpace(strValue))
                {
                    if (required)
                        throw new McpInvalidParamsException($"Required parameter '{paramName}' cannot be empty");
                    return null;
                }

                if (int.TryParse(strValue, out var intValue))
                    return intValue;

                throw new McpInvalidParamsException($"Parameter '{paramName}' must be a valid integer");
            }

            if (jsonElement.ValueKind == JsonValueKind.Null && required)
                throw new McpInvalidParamsException($"Required parameter '{paramName}' cannot be null");
        }

        // Try to convert directly
        try
        {
            return Convert.ToInt32(value);
        }
        catch
        {
            throw new McpInvalidParamsException($"Parameter '{paramName}' must be a valid integer");
        }
    }

    /// <summary>
    /// Parse a boolean parameter
    /// </summary>
    public static bool? ParseBool(Dictionary<string, object> args, string paramName, bool required = false)
    {
        if (!args.TryGetValue(paramName, out var value))
        {
            if (required)
                throw new McpInvalidParamsException($"Required parameter '{paramName}' is missing");
            return null;
        }

        if (value == null)
        {
            if (required)
                throw new McpInvalidParamsException($"Required parameter '{paramName}' cannot be null");
            return null;
        }

        // Handle JsonElement
        if (value is JsonElement jsonElement)
        {
            if (jsonElement.ValueKind == JsonValueKind.True)
                return true;

            if (jsonElement.ValueKind == JsonValueKind.False)
                return false;

            if (jsonElement.ValueKind == JsonValueKind.String)
            {
                var strValue = jsonElement.GetString();
                if (string.IsNullOrWhiteSpace(strValue))
                {
                    if (required)
                        throw new McpInvalidParamsException($"Required parameter '{paramName}' cannot be empty");
                    return null;
                }

                if (bool.TryParse(strValue, out var boolValue))
                    return boolValue;

                throw new McpInvalidParamsException($"Parameter '{paramName}' must be a valid boolean");
            }

            if (jsonElement.ValueKind == JsonValueKind.Null && required)
                throw new McpInvalidParamsException($"Required parameter '{paramName}' cannot be null");
        }

        // Try to convert directly
        try
        {
            return Convert.ToBoolean(value);
        }
        catch
        {
            throw new McpInvalidParamsException($"Parameter '{paramName}' must be a valid boolean");
        }
    }
}
