"""
Summary module - generates human-readable impact summaries for developers.

Creates actionable summaries of what changed and what needs testing.
"""

from typing import Dict, List, Optional
import re


def generate_impact_summary(
    symbol: str,
    change_type: str,
    classified_usage: Optional[Dict[str, List[str]]] = None,
    risk_level: Optional[str] = None
) -> str:
    """
    Generate a human-readable impact summary for a changed symbol.
    
    Creates a clear, actionable message showing:
    - What was changed
    - How the change was classified
    - What areas may be affected
    - Recommended validation steps
    
    Args:
        symbol: Name of the changed symbol
        change_type: Type of change (e.g., "function signature changed")
        classified_usage: Dict mapping category to list of affected modules
        risk_level: Risk classification (LOW/MEDIUM/HIGH)
        
    Returns:
        Formatted summary string
        
    Example:
        You changed: calculateDiscount()
        Change Type: function signature changed
        Risk Level: MEDIUM
        
        This may affect:
        - checkout pricing logic
        - invoice generation
        - promo eligibility
        
        Recommended Actions:
        - Run checkout pricing tests
        - Verify invoice totals are correct
        - Validate promo eligibility flow
    """
    if classified_usage is None:
        classified_usage = {}
    
    # Determine symbol display name
    symbol_display = _format_symbol_name(symbol, change_type)
    
    # Build header
    summary_lines = [
        f"You changed: {symbol_display}",
        f"Change Type: {change_type}",
    ]
    
    if risk_level:
        summary_lines.append(f"Risk Level: {risk_level}")
    
    summary_lines.append("")
    
    # Add affected areas
    affected_areas = _extract_affected_areas(classified_usage)
    if affected_areas:
        summary_lines.append("This may affect:")
        for area in affected_areas:
            summary_lines.append(f"  • {area}")
        summary_lines.append("")
    
    # Add recommended actions
    recommended_actions = _generate_recommended_actions(
        symbol,
        change_type,
        classified_usage,
        risk_level
    )
    
    if recommended_actions:
        summary_lines.append("Recommended Actions:")
        for action in recommended_actions:
            summary_lines.append(f"  • {action}")
    
    return "\n".join(summary_lines)


def _format_symbol_name(symbol: str, change_type: str) -> str:
    """
    Format symbol name with type hint based on change type.
    
    Args:
        symbol: Symbol name
        change_type: Type of change
        
    Returns:
        Formatted display name
    """
    # Determine symbol type from change type
    if "function" in change_type:
        return f"{symbol}()"
    elif "class" in change_type:
        return f"{symbol} (class)"
    elif "variable" in change_type or "enum" in change_type:
        return f"{symbol} (constant)"
    else:
        return symbol


def _extract_affected_areas(classified_usage: Dict[str, List[str]]) -> List[str]:
    """
    Extract affected areas from usage classification.
    
    Converts technical module names into user-facing descriptions.
    
    Args:
        classified_usage: Dict mapping categories to modules
        
    Returns:
        List of affected areas descriptions
    """
    affected_areas = []
    
    # Process by category for better organization
    category_descriptions = {
        "service": "logic flow",
        "services": "logic flow",
        "api": "user-facing behavior",
        "apis": "user-facing behavior",
        "model": "data integrity",
        "models": "data integrity",
        "controller": "request handling",
        "controllers": "request handling",
        "repository": "data access",
        "repositories": "data access",
        "util": "utility functions",
        "utils": "utility functions",
        "helper": "helper functions",
        "helpers": "helper functions",
        "test": "test coverage",
        "tests": "test coverage",
    }
    
    for category, modules in classified_usage.items():
        if not modules:
            continue
        
        # Get description for category
        category_lower = category.lower()
        description = category_descriptions.get(
            category_lower,
            f"{category.lower()} modules"
        )
        
        # Format affected area
        module_count = len(modules)
        if module_count == 1:
            area = f"{modules[0]} ({description})"
        else:
            area = f"{module_count} {description} ({', '.join(modules[:2])}...)"
        
        affected_areas.append(area)
    
    return affected_areas


def _generate_recommended_actions(
    symbol: str,
    change_type: str,
    classified_usage: Dict[str, List[str]],
    risk_level: Optional[str] = None
) -> List[str]:
    """
    Generate recommended validation actions based on change context.
    
    Args:
        symbol: Changed symbol
        change_type: Type of change
        classified_usage: Usage classification
        risk_level: Risk level
        
    Returns:
        List of recommended actions
    """
    actions = []
    
    # Determine base action based on change type
    if "removed" in change_type:
        actions.append(f"Search codebase for all usages of {symbol}")
        actions.append(f"Update or remove all calls to {symbol}")
        actions.append("Run full integration tests")
    
    elif "signature changed" in change_type:
        actions.append(f"Update all call sites of {symbol} with new signature")
        actions.append("Run tests on all updated modules")
        actions.append("Verify backward compatibility if needed")
    
    elif "added" in change_type:
        actions.append(f"Write unit tests for {symbol}")
        actions.append("Test integration with dependent modules")
        if "function" in change_type:
            actions.append("Document function parameters and return type")
    
    elif "modified" in change_type or "changed" in change_type:
        actions.append("Run tests on modified symbol")
        actions.append("Verify dependent modules handle the change")
        if "class" in change_type:
            actions.append("Check subclass and inheritance chain")
        elif "variable" in change_type:
            actions.append("Verify all code paths handle new value")
    
    # Add category-specific actions
    actions.extend(_get_category_specific_actions(classified_usage))
    
    # Add risk-level specific recommendations
    if risk_level == "HIGH":
        actions.insert(0, "⚠️  HIGH RISK - Comprehensive testing required")
        if "Run full integration tests" not in actions:
            actions.append("Run full integration tests")
        if "Verify in staging environment" not in actions:
            actions.append("Verify in staging environment before production")
    elif risk_level == "MEDIUM":
        if "Run tests" not in " ".join(actions).lower():
            actions.append("Run related test suite")
    
    # Deduplicate while preserving order
    seen = set()
    unique_actions = []
    for action in actions:
        if action not in seen:
            seen.add(action)
            unique_actions.append(action)
    
    return unique_actions[:5]  # Limit to 5 most important actions


def _get_category_specific_actions(classified_usage: Dict[str, List[str]]) -> List[str]:
    """
    Get recommended actions based on usage categories.
    
    Args:
        classified_usage: Usage classification by category
        
    Returns:
        List of category-specific recommended actions
    """
    actions = []
    
    for category, modules in classified_usage.items():
        if not modules:
            continue
        
        category_lower = category.lower()
        
        # API-related changes
        if "api" in category_lower:
            actions.append("Test API endpoints that use this symbol")
            actions.append("Update API documentation if needed")
        
        # Service-related changes
        elif "service" in category_lower:
            actions.append(f"Verify {modules[0]} service handles the change")
            actions.append("Load test affected service endpoints")
        
        # Model/Data-related changes
        elif "model" in category_lower or "repository" in category_lower:
            actions.append("Verify data migrations if needed")
            actions.append("Check database constraints and indexes")
        
        # Test coverage
        elif "test" in category_lower:
            actions.append("Update failing tests")
            actions.append("Add new tests for coverage gaps")
        
        # Utility/Helper functions
        elif "util" in category_lower or "helper" in category_lower:
            actions.append("Test all utility function call sites")
    
    return actions


def format_impact_report(
    symbols_with_impact: Dict[str, Dict],
    show_low_risk: bool = True
) -> str:
    """
    Format impact summary for multiple symbols.
    
    Args:
        symbols_with_impact: Dict mapping symbols to impact data
        show_low_risk: Whether to show LOW risk symbols
        
    Returns:
        Formatted report string
    """
    if not symbols_with_impact:
        return "No impact summary available"
    
    report_lines = ["=" * 80, "IMPACT SUMMARY REPORT", "=" * 80, ""]
    
    # Group by risk level
    high_risk = {}
    medium_risk = {}
    low_risk = {}
    
    for symbol, impact_data in symbols_with_impact.items():
        risk = impact_data.get("risk_level", "UNKNOWN")
        
        if risk == "HIGH":
            high_risk[symbol] = impact_data
        elif risk == "MEDIUM":
            medium_risk[symbol] = impact_data
        else:
            low_risk[symbol] = impact_data
    
    # Report HIGH risk
    if high_risk:
        report_lines.append("🔴 HIGH RISK CHANGES - Immediate Attention Required")
        report_lines.append("-" * 80)
        for symbol, data in high_risk.items():
            summary = generate_impact_summary(
                symbol,
                data.get("change_type", "unknown"),
                data.get("usage", {}),
                data.get("risk_level")
            )
            report_lines.append(summary)
            report_lines.append("")
    
    # Report MEDIUM risk
    if medium_risk:
        report_lines.append("🟡 MEDIUM RISK CHANGES - Review Required")
        report_lines.append("-" * 80)
        for symbol, data in medium_risk.items():
            summary = generate_impact_summary(
                symbol,
                data.get("change_type", "unknown"),
                data.get("usage", {}),
                data.get("risk_level")
            )
            report_lines.append(summary)
            report_lines.append("")
    
    # Report LOW risk (optional)
    if show_low_risk and low_risk:
        report_lines.append("🟢 LOW RISK CHANGES")
        report_lines.append("-" * 80)
        for symbol, data in low_risk.items():
            summary = generate_impact_summary(
                symbol,
                data.get("change_type", "unknown"),
                data.get("usage", {}),
                data.get("risk_level")
            )
            report_lines.append(summary)
            report_lines.append("")
    
    report_lines.append("=" * 80)
    return "\n".join(report_lines)


def classify_usage_by_category(usage_locations: List[str]) -> Dict[str, List[str]]:
    """
    Classify usage locations by category.
    
    Args:
        usage_locations: List of module/location names
        
    Returns:
        Dict mapping categories to lists of modules
    """
    classified = {
        "service": [],
        "api": [],
        "model": [],
        "controller": [],
        "repository": [],
        "test": [],
        "util": [],
        "other": [],
    }
    
    keywords = {
        "service": ["service", "svc"],
        "api": ["api", "route", "endpoint"],
        "model": ["model", "schema"],
        "controller": ["controller", "ctrl", "handler"],
        "repository": ["repo", "repository", "dao"],
        "test": ["test", "spec"],
        "util": ["util", "helper", "common"],
    }
    
    for location in usage_locations:
        location_lower = location.lower()
        classified_flag = False
        
        for category, patterns in keywords.items():
            if any(pattern in location_lower for pattern in patterns):
                classified[category].append(location)
                classified_flag = True
                break
        
        if not classified_flag:
            classified["other"].append(location)
    
    # Remove empty categories
    return {k: v for k, v in classified.items() if v}


def suggest_testing_strategy(
    symbol: str,
    change_type: str,
    classified_usage: Dict[str, List[str]],
    risk_level: str
) -> List[str]:
    """
    Suggest testing strategy based on change context.
    
    Args:
        symbol: Changed symbol
        change_type: Type of change
        classified_usage: Usage classification
        risk_level: Risk level
        
    Returns:
        List of testing steps
    """
    strategy = []
    
    # Base strategy on change type
    if "added" in change_type:
        strategy.append("1. Unit tests for new symbol")
        strategy.append("2. Integration tests with dependent modules")
    elif "removed" in change_type:
        strategy.append("1. Find all usages (grep/search)")
        strategy.append("2. Update or remove all call sites")
        strategy.append("3. Regression tests on all affected modules")
    elif "signature changed" in change_type:
        strategy.append("1. Update all call sites to new signature")
        strategy.append("2. Test each updated call site")
        strategy.append("3. Regression tests on dependent modules")
    elif "modified" in change_type:
        strategy.append("1. Unit tests on modified behavior")
        strategy.append("2. Edge case testing")
        strategy.append("3. Regression tests on dependent code")
    
    # Add category-specific testing
    if "test" in classified_usage:
        strategy.append(f"4. Fix {len(classified_usage['test'])} failing test(s)")
    
    if "service" in classified_usage:
        strategy.append(f"5. Service-level integration tests")
    
    if "api" in classified_usage:
        strategy.append(f"6. API endpoint testing")
    
    # Risk-level specific
    if risk_level == "HIGH":
        strategy.insert(0, "⚠️  HIGH RISK - Execute full test suite")
        strategy.append("7. Manual QA in staging")
        strategy.append("8. Performance benchmarking")
    elif risk_level == "MEDIUM":
        strategy.append("5. Full test suite for affected modules")
    
    return strategy
