"""
Error handling utilities for TouchDesigner MCP Web server
Provides standardized error categorization, formatting, and handling
"""

from enum import Enum
import functools
import traceback
from typing import Callable, Optional, TypeVar

from utils.logging import log_message
from utils.result import Result, error_result
from utils.types import LogLevel

T = TypeVar("T")


class ErrorCategory(Enum):
	"""
	Error categories for better classification and handling
	"""

	INTERNAL = "INTERNAL"
	VALIDATION = "VALIDATION"
	NOT_FOUND = "NOT_FOUND"
	PERMISSION = "PERMISSION"
	NETWORK = "NETWORK"
	EXTERNAL = "EXTERNAL"

	def __str__(self) -> str:
		return self.value


def categorize_error(exception: Exception) -> ErrorCategory:
	"""
	Categorize an exception based on its type and message

	Args:
	    exception: The exception to categorize

	Returns:
	    Appropriate ErrorCategory
	"""
	error_message = str(exception).lower()

	if isinstance(exception, ValueError):
		return ErrorCategory.VALIDATION
	elif (
		isinstance(exception, FileNotFoundError)
		or "not found" in error_message
		or "doesn't exist" in error_message
	):
		return ErrorCategory.NOT_FOUND
	elif "permission" in error_message or "access denied" in error_message:
		return ErrorCategory.PERMISSION
	elif "network" in error_message or "connection" in error_message:
		return ErrorCategory.NETWORK
	elif "external" in error_message or "service unavailable" in error_message:
		return ErrorCategory.EXTERNAL

	return ErrorCategory.INTERNAL


def format_error(message: str, category: Optional[ErrorCategory] = None) -> str:
	"""
	Format an error message with its category

	Args:
	    message: The error message
	    category: Error category (defaults to INTERNAL)

	Returns:
	    Formatted error message
	"""
	if category is None:
		category = ErrorCategory.INTERNAL

	return f"{category}: {message}"


def handle_service_errors(func: Callable[..., Result]) -> Callable[..., Result]:
	"""
	Decorator to handle errors in service methods and convert them to Result type

	Args:
	    func: The service method to decorate

	Returns:
	    Wrapped function that catches exceptions and returns Result
	"""

	@functools.wraps(func)
	def wrapper(*args, **kwargs) -> Result:
		try:
			return func(*args, **kwargs)
		except Exception as e:
			category = categorize_error(e)

			func_name = func.__name__
			log_message(f"Error in {func_name}: {str(e)}", LogLevel.ERROR)
			log_message(traceback.format_exc(), LogLevel.DEBUG)

			error_message = format_error(str(e), category)
			return error_result(error_message, {"errorCategory": category})

	return wrapper
