using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace io.github.hatayama.uLoopMCP
{
    /// <summary>
    /// Translation result from Translator before formatting
    /// </summary>
    public class TranslationOutput
    {
        public string FriendlyMessage { get; set; } = "";
        public string Explanation { get; set; } = "";
        public string Example { get; set; } = "";
        public List<string> Solutions { get; set; } = new();
        public List<string> LearningTips { get; set; } = new();
    }

    /// <summary>
    /// Translate raw errors/exceptions into structured data (no severity weighting)
    /// </summary>
    public interface IErrorTranslator
    {
        TranslationOutput TranslateFromException(Exception exception);
        TranslationOutput TranslateFromMessage(string errorMessage);
    }

    /// <summary>
    /// Format translation into DTO with severity weighting and final output shape
    /// </summary>
    public interface IErrorFormatter
    {
        UserFriendlyErrorDto Format(TranslationOutput translation, string originalError, Exception exception = null);
    }

    /// <summary>
    /// Default translator using pattern dictionary and simple fallbacks
    /// </summary>
    public class DefaultErrorTranslator : IErrorTranslator
    {
        private readonly ErrorTranslationDictionary _dictionary = new();
        private readonly FriendlyMessageGenerator _messageGenerator = new();

        public TranslationOutput TranslateFromException(Exception exception)
        {
            if (exception == null)
            {
                return new TranslationOutput
                {
                    FriendlyMessage = "Internal error",
                    Explanation = string.Empty,
                    Example = string.Empty,
                    Solutions = new List<string>(),
                    LearningTips = new List<string>()
                };
            }

            if (exception is McpSecurityException securityException)
            {
                return new TranslationOutput
                {
                    FriendlyMessage = "Tool blocked by security settings",
                    Explanation = securityException.SecurityReason ?? string.Empty,
                    Solutions = new List<string>
                    {
                        "Open uLoopMCP Security Settings and enable the required permission"
                    }
                };
            }

            if (exception is TimeoutException)
            {
                return new TranslationOutput
                {
                    FriendlyMessage = "Request timeout",
                    Explanation = exception.Message,
                    Solutions = new List<string>
                    {
                        "Increase timeout or optimize the operation to complete faster"
                    }
                };
            }

            if (exception is ToolDisabledException disabledException)
            {
                return new TranslationOutput
                {
                    FriendlyMessage = $"Tool '{disabledException.ToolName}' is disabled. To enable it, go to {McpUIConstants.TOOL_SETTINGS_MENU_PATH}",
                    Explanation = "This tool has been disabled in project settings.",
                    Solutions = new List<string>
                    {
                        $"Enable '{disabledException.ToolName}' in {McpUIConstants.TOOL_SETTINGS_MENU_PATH}"
                    }
                };
            }

            if (exception is ParameterValidationException)
            {
                return new TranslationOutput
                {
                    FriendlyMessage = exception.Message,
                    Explanation = string.Empty,
                    Solutions = new List<string>
                    {
                        "Fix parameter types/values according to the tool schema"
                    }
                };
            }

            return new TranslationOutput
            {
                FriendlyMessage = "Internal error",
                Explanation = exception.Message
            };
        }

        public TranslationOutput TranslateFromMessage(string errorMessage)
        {
            ErrorPattern pattern = _dictionary.FindPattern(errorMessage);

            string friendly = pattern?.FriendlyMessage ?? _messageGenerator.TranslateError(errorMessage);
            string explanation = pattern?.Explanation ?? string.Empty;
            string example = pattern?.Example ?? string.Empty;
            List<string> solutions = pattern?.Solutions ?? new List<string>();
            List<string> tips = GetLearningTips(errorMessage);

            return new TranslationOutput
            {
                FriendlyMessage = friendly,
                Explanation = explanation,
                Example = example,
                Solutions = solutions,
                LearningTips = tips
            };
        }

        private List<string> GetLearningTips(string errorMessage)
        {
            List<string> tips = new();

            if (errorMessage.Contains("Top-level statements"))
            {
                tips.Add("In Dynamic Tool, you can write code directly");
                tips.Add("Class and namespace declarations are not required");
            }

            if (errorMessage.Contains("not all code paths return"))
            {
                tips.Add("Add a return statement at the end of the code");
                tips.Add("Return the execution result as a string");
            }

            if (errorMessage.Contains("ambiguous reference"))
            {
                tips.Add("Clearly distinguish between UnityEngine.Object and System.Object");
                tips.Add("Using the full name (UnityEngine.Object) is safer");
            }

            return tips;
        }
    }

    /// <summary>
    /// Default formatter applying severity weighting and assembling the DTO
    /// </summary>
    public class DefaultErrorFormatter : IErrorFormatter
    {
        public UserFriendlyErrorDto Format(TranslationOutput translation, string originalError, Exception exception = null)
        {
            return new UserFriendlyErrorDto
            {
                OriginalError = originalError ?? string.Empty,
                FriendlyMessage = translation?.FriendlyMessage ?? string.Empty,
                Explanation = translation?.Explanation ?? string.Empty,
                Example = translation?.Example ?? string.Empty,
                SuggestedSolutions = translation?.Solutions ?? new List<string>(),
                LearningTips = translation?.LearningTips ?? new List<string>(),
                Severity = DetermineSeverity(originalError, exception)
            };
        }

        private ErrorSeverity DetermineSeverity(string errorMessage, Exception exception)
        {
            if (exception != null)
            {
                if (exception is McpSecurityException)
                {
                    return ErrorSeverity.High;
                }
                if (exception is TimeoutException)
                {
                    return ErrorSeverity.Medium;
                }
                if (exception is ToolDisabledException)
                {
                    return ErrorSeverity.Medium;
                }
                if (exception is ParameterValidationException)
                {
                    return ErrorSeverity.Low;
                }
                return ErrorSeverity.High;
            }

            string msg = errorMessage ?? string.Empty;
            if (msg.Contains("Top-level statements") || msg.Contains("not all code paths"))
            {
                return ErrorSeverity.High;
            }
            if (msg.Contains("ambiguous reference"))
            {
                return ErrorSeverity.Medium;
            }
            return ErrorSeverity.Low;
        }
    }

    /// <summary>
    /// Related Classes: FriendlyMessageGenerator, ErrorTranslationDictionary
    /// Now delegates to Translator and Formatter
    /// </summary>
    public class UserFriendlyErrorConverter
    {
        private readonly IErrorTranslator _translator;
        private readonly IErrorFormatter _formatter;

        public UserFriendlyErrorConverter()
        {
            _translator = new DefaultErrorTranslator();
            _formatter = new DefaultErrorFormatter();
        }

        public UserFriendlyErrorConverter(IErrorTranslator translator, IErrorFormatter formatter)
        {
            _translator = translator ?? new DefaultErrorTranslator();
            _formatter = formatter ?? new DefaultErrorFormatter();
        }

        /// <summary>
        /// Convert an exception to an enhanced, user-friendly error response
        /// </summary>
        public UserFriendlyErrorDto ProcessException(Exception exception)
        {
            if (exception == null)
            {
                return new UserFriendlyErrorDto
                {
                    OriginalError = string.Empty,
                    FriendlyMessage = "Internal error",
                    Explanation = string.Empty,
                    Example = string.Empty,
                    SuggestedSolutions = new List<string>(),
                    LearningTips = new List<string>(),
                    Severity = ErrorSeverity.High
                };
            }

            TranslationOutput translation = _translator.TranslateFromException(exception);
            return _formatter.Format(translation, exception.Message, exception);
        }

        /// <summary>
        /// Convert execution result errors into a more understandable format
        /// </summary>
        public UserFriendlyErrorDto ProcessError(
            ExecutionResult originalResult, 
            string originalCode)
        {
            string errorMessage = originalResult.ErrorMessage ?? string.Empty;
            if (originalResult.Logs?.Any() == true)
            {
                string combinedErrors = string.Join(" ", originalResult.Logs);
                if (!string.IsNullOrEmpty(combinedErrors))
                {
                    errorMessage += " " + combinedErrors;
                }
            }

            TranslationOutput translation = _translator.TranslateFromMessage(errorMessage);
            return _formatter.Format(translation, errorMessage);
        }
    }

    /// <summary>
    /// Error Translation Dictionary - Translating Common Error Patterns into Understandable Messages
    /// </summary>
    public class ErrorTranslationDictionary
    {
        private static readonly Dictionary<string, ErrorPattern> Patterns = new()
        {
            ["Top-level statements must precede"] = new ErrorPattern
            {
                PatternRegex = @"Top-level statements must precede",
                FriendlyMessage = "There is an issue with the code structure",
                Explanation = "In the Dynamic Tool, class and namespace declarations are not required. Write Unity API processing directly.",
                Example = @"AVOID: namespace Test { class MyClass { void Method() { ... } } }

CORRECT: GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.transform.position = Vector3.zero;
return ""Cube creation completed"";",
                Solutions = new List<string>
                {
                    "Remove class definition and write only the code inside the method",
                    "Remove namespace declaration", 
                    "Keep using statements and extract only the main processing"
                }
            },
            
            ["not all code paths return a value"] = new ErrorPattern
            {
                PatternRegex = @"not all code paths return",
                FriendlyMessage = "A return value is required at the end of the code",
                Explanation = "In the Dynamic Tool, you must return the execution result. Please add a return statement at the end of the processing.",
                Example = @"AVOID: GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
Debug.Log(""Completed"");

CORRECT: GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
Debug.Log(""Completed"");
return ""Cube creation completed"";",
                Solutions = new List<string>
                {
                    "Add 'return \"Execution completed\";' at the end of the code",
                    "Add return statements to all paths of conditional branching",
                    "Return the execution result as a string"
                }
            },

            ["Object' is an ambiguous reference"] = new ErrorPattern
            {
                PatternRegex = @"'Object' is an ambiguous reference",
                FriendlyMessage = "Object class reference is ambiguous",
                Explanation = "UnityEngine.Object and System.Object are mixed. Please specify explicitly.",
                Example = @"AVOID: Object.DestroyImmediate(obj);

CORRECT: UnityEngine.Object.DestroyImmediate(obj);",
                Solutions = new List<string>
                {
                    "Explicitly specify UnityEngine.Object",
                    "Use full name description"
                }
            }
        };

        public ErrorPattern FindPattern(string errorMessage)
        {
            foreach (var kvp in Patterns)
            {
                if (Regex.IsMatch(errorMessage, kvp.Value.PatternRegex))
                {
                    return kvp.Value;
                }
            }
            return null;
        }
    }

    /// <summary>
    /// User-Friendly Message Generation Feature
    /// </summary>
    public class FriendlyMessageGenerator
    {
        public string TranslateError(string originalError)
        {
            // Basic error translation logic
            if (originalError.Contains("Top-level statements"))
            {
                return "There is an issue with the code structure. Class and namespace definitions are not required.";
            }
            
            if (originalError.Contains("not all code paths return"))
            {
                return "A return value is required at the end of the code. Please add 'return \"Completed\";'.";
            }
            
            if (originalError.Contains("ambiguous reference"))
            {
                return "Class reference is ambiguous. Please explicitly write UnityEngine.Object.";
            }
            
            if (originalError.Contains("Identifier expected"))
            {
                return "Syntax error. Please verify the code syntax.";
            }
            
            return originalError; // Fallback
        }
    }

    /// <summary>
    /// Error Pattern Definition
    /// </summary>
    public class ErrorPattern
    {
        public string PatternRegex { get; set; } = "";
        public string FriendlyMessage { get; set; } = "";
        public string Explanation { get; set; } = "";
        public string Example { get; set; } = "";
        public List<string> Solutions { get; set; } = new();
    }

    /// <summary>
    /// User-friendly error DTO for API/UI surfaces
    /// </summary>
    public class UserFriendlyErrorDto
    {
        public string OriginalError { get; set; } = "";
        public string FriendlyMessage { get; set; } = "";
        public string Explanation { get; set; } = "";
        public string Example { get; set; } = "";
        public List<string> SuggestedSolutions { get; set; } = new();
        public List<string> LearningTips { get; set; } = new();
        public ErrorSeverity Severity { get; set; }
    }

    /// <summary>
    /// Error Severity
    /// </summary>
    public enum ErrorSeverity
    {
        Low,
        Medium,
        High,
        Critical
    }
}