"""
Pydantic models and TypedDict structures for MCP server responses.

This module provides type-safe, AI-agent-friendly data structures that ensure
consistent, well-documented responses across all MCP tools.
"""

from typing import Dict, List, Optional, Union, Literal, Any
from pathlib import Path
from pydantic import BaseModel, Field, field_validator, ConfigDict
from enum import Enum
from datetime import datetime


# ============================================================================
# Base Models and Enums
# ============================================================================

class Status(str, Enum):
    """Response status indicators for AI agents."""
    SUCCESS = "success"
    WARNING = "warning"
    ERROR = "error"
    INFO = "info"


class Severity(str, Enum):
    """Security and issue severity levels."""
    CRITICAL = "critical"
    HIGH = "high"
    MEDIUM = "medium"
    LOW = "low"
    INFO = "info"


class TestType(str, Enum):
    """Types of tests that can be generated."""
    UNIT = "unit"
    INTEGRATION = "integration"
    FUNCTIONAL = "functional"
    PERFORMANCE = "performance"
    SECURITY = "security"
    E2E = "end_to_end"


class MCPResponse(BaseModel):
    """
    Base response model for all MCP tools.
    
    Every MCP tool response inherits from this to ensure consistency
    and AI-agent-friendly structure.
    """
    status: Status = Field(description="Operation status")
    message: str = Field(description="Human-readable status message")
    data: Any = Field(description="The actual response data")
    next_steps: List[str] = Field(
        default_factory=list,
        description="Suggested follow-up actions for AI agents"
    )
    related_tools: List[str] = Field(
        default_factory=list,
        description="Related MCP tools that might be helpful"
    )
    examples: List[str] = Field(
        default_factory=list,
        description="Example commands or usage patterns"
    )
    
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "status": "success",
                "message": "Analysis completed successfully",
                "data": {},
                "next_steps": ["Run 'generate_unit_tests' for uncovered modules"],
                "related_tools": ["generate_unit_tests", "create_test_plan"],
                "examples": ["pytest -xvs tests/unit/test_logger.py"]
            }
        }
    )


# ============================================================================
# Coverage Models
# ============================================================================

class ModuleCoverage(BaseModel):
    """Coverage information for a single module."""
    module_path: Path = Field(description="Path to the module file")
    coverage_percent: float = Field(ge=0, le=100, description="Coverage percentage")
    covered_lines: int = Field(ge=0, description="Number of covered lines")
    total_lines: int = Field(ge=0, description="Total number of lines")
    missing_lines: List[int] = Field(
        default_factory=list,
        description="Line numbers that are not covered"
    )
    business_critical: bool = Field(
        default=False,
        description="Whether this module is business-critical"
    )
    
    @field_validator('coverage_percent')
    @classmethod
    def round_coverage(cls, v: float) -> float:
        """Round coverage to 2 decimal places."""
        return round(v, 2)


class CoverageAnalysis(MCPResponse):
    """Comprehensive coverage analysis result."""
    pytest_commands: List[str] = Field(
        default_factory=list,
        description="Ready-to-run pytest commands for improving coverage"
    )


class PytestCommands(MCPResponse):
    """Generated pytest commands with explanations."""
    data: List[Dict[str, str]] = Field(
        description="List of pytest commands with descriptions",
        json_schema_extra={
            "example": [{
                "command": "pytest -xvs -k 'test_business_metrics' --cov=storm_logger.utils.business_metrics",
                "description": "Run business metrics tests with coverage",
                "expected_impact": "Will increase coverage by ~5%"
            }]
        }
    )


# ============================================================================
# Testing Models
# ============================================================================

class TestGap(BaseModel):
    """Identified gap in test coverage."""
    module: str = Field(description="Module with missing tests")
    untested_functions: List[str] = Field(
        default_factory=list,
        description="Functions without tests"
    )
    untested_classes: List[str] = Field(
        default_factory=list,
        description="Classes without tests"
    )
    priority: Severity = Field(description="Priority for testing this gap")
    business_impact: str = Field(description="Business impact if untested")


class TestGapAnalysis(MCPResponse):
    """Comprehensive test gap analysis."""
    data: Dict[str, Any] = Field(
        description="Test gap analysis results",
        json_schema_extra={
            "example": {
                "total_gaps": 15,
                "critical_gaps": 3,
                "gaps_by_module": {},
                "untested_functions": [],
                "untested_classes": [],
                "priority_order": []
            }
        }
    )


class TestGenerationResult(MCPResponse):
    """Result of test generation."""
    data: Dict[str, Any] = Field(
        description="Generated test information",
        json_schema_extra={
            "example": {
                "test_file_path": "tests/unit/test_new_module.py",
                "test_code": "# Generated test code",
                "fixtures_needed": ["storm_logger", "mock_config"],
                "markers_suggested": ["unit", "fast"],
                "coverage_impact": 15.5,
                "imports_required": ["pytest", "unittest.mock"]
            }
        }
    )
    pytest_commands: List[str] = Field(
        default_factory=list,
        description="Commands to run the generated tests"
    )


class TestEnhancement(BaseModel):
    """Suggested enhancement for existing tests."""
    test_file: Path = Field(description="Test file to enhance")
    current_quality: float = Field(
        ge=0, le=100,
        description="Current test quality score"
    )
    suggestions: List[Dict[str, str]] = Field(
        description="Specific enhancement suggestions"
    )
    code_examples: List[str] = Field(
        default_factory=list,
        description="Example code for improvements"
    )


class TestQualityAnalysis(MCPResponse):
    """Test quality analysis results."""
    data: Dict[str, Any] = Field(
        description="Test quality metrics and suggestions",
        json_schema_extra={
            "example": {
                "overall_quality": 75.5,
                "files_analyzed": 10,
                "enhancements": [],
                "missing_assertions": [],
                "missing_edge_cases": []
            }
        }
    )


class TestPlan(MCPResponse):
    """Comprehensive test implementation plan."""
    data: Dict[str, Any] = Field(
        description="Test plan details",
        json_schema_extra={
            "example": {
                "phases": [],
                "priority_modules": [],
                "estimated_effort_days": 10,
                "test_types_needed": ["unit", "integration"],
                "fixture_requirements": []
            }
        }
    )


class PytestConfig(MCPResponse):
    """Generated pytest configuration."""
    data: Dict[str, Any] = Field(
        description="Pytest configuration details",
        json_schema_extra={
            "example": {
                "config_file_content": "[tool.pytest.ini_options]...",
                "markers": {"unit": "Unit tests", "slow": "Slow tests"},
                "recommended_plugins": ["pytest-cov", "pytest-xdist"],
                "coverage_settings": {"fail_under": 90}
            }
        }
    )


# ============================================================================
# Security Models
# ============================================================================

class SecurityIssue(BaseModel):
    """Identified security issue."""
    severity: Severity = Field(description="Issue severity")
    issue_type: str = Field(description="Type of security issue")
    file_path: Path = Field(description="File containing the issue")
    line_number: Optional[int] = Field(default=None, description="Line number")
    description: str = Field(description="Issue description")
    recommendation: str = Field(description="How to fix the issue")
    cwe_id: Optional[str] = Field(default=None, description="CWE identifier")


class SecurityScanResult(MCPResponse):
    """Security scan results."""
    data: Dict[str, Any] = Field(
        description="Security scan findings",
        json_schema_extra={
            "example": {
                "total_issues": 5,
                "critical_issues": 1,
                "issues_by_severity": {},
                "issues": []
            }
        }
    )
    remediation_commands: List[str] = Field(
        default_factory=list,
        description="Commands to fix security issues"
    )


# ============================================================================
# Pattern Models
# ============================================================================

class PatternMatcherCode(MCPResponse):
    """Generated pattern matcher code."""
    data: Dict[str, str] = Field(
        description="Pattern matcher implementation",
        json_schema_extra={
            "example": {
                "class_name": "PaymentCardMatcher",
                "code": "class PaymentCardMatcher...",
                "test_code": "def test_payment_card_matcher()...",
                "usage_example": "matcher = PaymentCardMatcher()..."
            }
        }
    )


class PatternConflict(BaseModel):
    """Detected pattern conflict."""
    pattern1: str = Field(description="First conflicting pattern")
    pattern2: str = Field(description="Second conflicting pattern")
    conflict_type: str = Field(description="Type of conflict")
    example_text: str = Field(description="Text that matches both")
    resolution: str = Field(description="Suggested resolution")


# ============================================================================
# Code Analysis Models
# ============================================================================

class CodeQualityMetrics(BaseModel):
    """Code quality metrics."""
    complexity: float = Field(description="Cyclomatic complexity")
    maintainability_index: float = Field(description="Maintainability index")
    technical_debt_ratio: float = Field(description="Technical debt ratio")
    code_smells: int = Field(description="Number of code smells")
    duplicated_lines_percent: float = Field(description="Percentage of duplicated lines")


class CodeAnalysis(MCPResponse):
    """Comprehensive code analysis result."""
    data: Dict[str, Any] = Field(
        description="Code analysis findings",
        json_schema_extra={
            "example": {
                "quality_metrics": {},
                "type_hint_coverage": 85.0,
                "docstring_coverage": 70.0,
                "issues": [],
                "suggestions": []
            }
        }
    )
    improvement_commands: List[str] = Field(
        default_factory=list,
        description="Commands to improve code quality"
    )


# ============================================================================
# Project Structure Models
# ============================================================================

class ProjectStructure(MCPResponse):
    """Project structure analysis."""
    data: Dict[str, Any] = Field(
        description="Project structure information",
        json_schema_extra={
            "example": {
                "total_files": 150,
                "python_files": 120,
                "test_files": 40,
                "coverage_percent": 85.5,
                "architecture_style": "modular",
                "framework": "standalone"
            }
        }
    )


class DevelopmentPlan(MCPResponse):
    """Generated development plan."""
    data: Dict[str, Any] = Field(
        description="Development plan details",
        json_schema_extra={
            "example": {
                "phases": [],
                "timeline_weeks": 12,
                "priorities": [],
                "milestones": [],
                "resource_requirements": {}
            }
        }
    )


# ============================================================================
# Error Models
# ============================================================================

class MCPToolError(BaseModel):
    """Structured error response for AI agents."""
    error_type: str = Field(description="Type of error")
    message: str = Field(description="Error message")
    suggestions: List[str] = Field(
        default_factory=list,
        description="Suggestions to resolve the error"
    )
    related_tools: List[str] = Field(
        default_factory=list,
        description="Tools that might help resolve the issue"
    )
    documentation_link: Optional[str] = Field(
        default=None,
        description="Link to relevant documentation"
    )
    
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "error_type": "FileNotFoundError",
                "message": "Test file not found: tests/unit/test_missing.py",
                "suggestions": [
                    "Check if the file path is correct",
                    "Use 'find_test_files' to discover existing tests",
                    "Create the test file with 'generate_unit_tests'"
                ],
                "related_tools": ["find_test_files", "generate_unit_tests"],
                "documentation_link": "https://docs.pytest.org/en/stable/"
            }
        }
    )


# ============================================================================
# AI Agent Standards Models
# ============================================================================

class AIFriendlinessCheck(MCPResponse):
    """Result of AI-friendliness code check."""
    data: Dict[str, Any] = Field(
        description="AI-friendliness analysis results",
        json_schema_extra={
            "example": {
                "file": "example.py",
                "score": 85,
                "status": "pass",
                "issues": [],
                "recommendations": [],
                "check_level": "comprehensive"
            }
        }
    )


class NamingConventionViolation(BaseModel):
    """Details of a naming convention violation."""
    pattern: str = Field(description="The problematic pattern found")
    line: Optional[int] = Field(default=None, description="Line number where pattern occurs")
    severity: Severity = Field(description="Severity of the violation")
    recommendation: str = Field(description="How to fix the violation")
    
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "pattern": "_refactored",
                "line": 42,
                "severity": "high",
                "recommendation": "Modify original file instead of creating _refactored version"
            }
        }
    )


class CodeChangeExplanation(MCPResponse):
    """Structured explanation of code changes."""
    data: Dict[str, Any] = Field(
        description="Code change analysis",
        json_schema_extra={
            "example": {
                "summary": "Code was refactored for clarity",
                "added_lines": 25,
                "removed_lines": 30,
                "change_type": "refactoring",
                "details": ["Extracted helper functions", "Improved naming"],
                "ai_notes": ["Changes are AI-friendly"],
                "ai_recommendation": "Good refactoring approach"
            }
        }
    )