"""DSPy signatures for error analysis and fix generation."""

from __future__ import annotations

# DSPy is optional - only import if installed
_dspy_available = False
try:
    import dspy
    _dspy_available = True
except ImportError:
    dspy = None


def is_available() -> bool:
    """Check if DSPy is available."""
    return _dspy_available


if _dspy_available:

    class AnalyzeError(dspy.Signature):
        """Analyze a production error to determine root cause.

        Given error details including exception type, message, stack trace,
        and I/O transcript, determine the most likely root cause.
        """

        exception_type: str = dspy.InputField(desc="The type of exception raised (e.g., KeyError, ValueError)")
        message: str = dspy.InputField(desc="The error message")
        stack_trace: str = dspy.InputField(desc="Full stack trace showing call hierarchy")
        io_transcript: str = dspy.InputField(desc="HTTP/SQL/time operations before error occurred")
        code_context: str = dspy.InputField(desc="Relevant source code around error location")

        root_cause: str = dspy.OutputField(desc="Brief description of why the error occurred")
        category: str = dspy.OutputField(
            desc="Category: null_reference, type_error, validation, api_error, race_condition, config, other"
        )
        confidence: float = dspy.OutputField(desc="Confidence score between 0 and 1")

    class GenerateFix(dspy.Signature):
        """Generate a fix for an analyzed error.

        Given the error analysis and code context, generate a minimal
        unified diff that fixes the issue.
        """

        exception_type: str = dspy.InputField(desc="The exception type")
        root_cause: str = dspy.InputField(desc="Analyzed root cause of the error")
        code_context: str = dspy.InputField(desc="Source code around error location")
        similar_fixes: str = dspy.InputField(desc="Similar past fixes that worked, with success rates")

        fix_strategy: str = dspy.OutputField(desc="Brief description of the fix approach")
        unified_diff: str = dspy.OutputField(desc="Unified diff format patch starting with --- and +++")
        explanation: str = dspy.OutputField(desc="Explanation of why this fix works")

    class ClassifyError(dspy.Signature):
        """Classify an error for routing to appropriate fix strategy."""

        exception_type: str = dspy.InputField(desc="The exception type")
        message: str = dspy.InputField(desc="The error message")
        stack_trace: str = dspy.InputField(desc="Stack trace")

        category: str = dspy.OutputField(
            desc="One of: null_reference, type_error, validation, timeout, auth, network, config, other"
        )
        severity: str = dspy.OutputField(desc="One of: critical, high, medium, low")
        is_user_facing: bool = dspy.OutputField(desc="Whether error is visible to end users")

    class ExtractFixPattern(dspy.Signature):
        """Extract a reusable fix pattern from a successful fix.

        Used to build the pattern database for similar future errors.
        """

        exception_type: str = dspy.InputField(desc="The exception type that was fixed")
        exception_message: str = dspy.InputField(desc="The error message")
        original_code: str = dspy.InputField(desc="Code before the fix")
        fixed_code: str = dspy.InputField(desc="Code after the fix")
        fix_explanation: str = dspy.InputField(desc="Why the fix works")

        pattern_name: str = dspy.OutputField(desc="Short name for this fix pattern (e.g., 'null_check_before_access')")
        pattern_description: str = dspy.OutputField(desc="When to apply this pattern")
        code_template: str = dspy.OutputField(desc="Parameterized code template with {{placeholders}}")
        applicability: str = dspy.OutputField(desc="Conditions when this pattern should be applied")

else:
    # Stub classes when DSPy not available
    class AnalyzeError:
        """Stub for AnalyzeError when DSPy not installed."""
        pass

    class GenerateFix:
        """Stub for GenerateFix when DSPy not installed."""
        pass

    class ClassifyError:
        """Stub for ClassifyError when DSPy not installed."""
        pass

    class ExtractFixPattern:
        """Stub for ExtractFixPattern when DSPy not installed."""
        pass
