"""Performance scoring - pure functions for scoring metrics.

This module provides clean, testable functions for scoring performance metrics.
All scoring logic is pure (no side effects) and operation-aware.
"""

from dataclasses import dataclass
from typing import Dict, List

import sys
import os

sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from core.metrics import PerformanceMetrics


@dataclass
class PerformanceScore:
    """Performance score with detailed breakdown."""

    total_score: float  # 0-100
    grade: str  # S, A+, A, B, C, D, F
    response_time_score: float  # Points from response time
    query_efficiency_score: float  # Points from query efficiency
    memory_efficiency_score: float  # Points from memory efficiency
    penalties: List[str]  # What caused point deductions
    strengths: List[str]  # What earned points


def _calculate_grade(score: float) -> str:
    """Convert numeric score to letter grade.

    Args:
        score: Numeric score (0-100)

    Returns:
        Letter grade (S, A+, A, B, C, D, F)
    """
    if score >= 95:
        return "S"  # Perfect/Superior
    elif score >= 90:
        return "A+"
    elif score >= 80:
        return "A"
    elif score >= 70:
        return "B"
    elif score >= 60:
        return "C"
    elif score >= 50:
        return "D"
    else:
        return "F"


def _score_response_time(response_time_ms: float) -> tuple[float, List[str], List[str]]:
    """Score response time (0-30 points).

    Args:
        response_time_ms: Response time in milliseconds

    Returns:
        Tuple of (score, penalties, strengths)
    """
    penalties = []
    strengths = []

    if response_time_ms <= 10:
        score = 30.0
        strengths.append(f"Lightning fast response ({response_time_ms:.1f}ms)")
    elif response_time_ms <= 25:
        score = 28.0
        strengths.append(f"Excellent response time ({response_time_ms:.1f}ms)")
    elif response_time_ms <= 50:
        score = 25.0
        strengths.append(f"Very good response time ({response_time_ms:.1f}ms)")
    elif response_time_ms <= 100:
        score = 20.0
        strengths.append(f"Good response time ({response_time_ms:.1f}ms)")
    elif response_time_ms <= 200:
        score = 12.0
        penalties.append(f"Acceptable response time ({response_time_ms:.1f}ms)")
    elif response_time_ms <= 500:
        score = 5.0
        penalties.append(f"Slow response time ({response_time_ms:.1f}ms)")
    elif response_time_ms <= 1000:
        score = 2.0
        penalties.append(f"Very slow response time ({response_time_ms:.1f}ms)")
    else:
        score = 0.0
        penalties.append(f"Extremely slow response time ({response_time_ms:.1f}ms)")

    return score, penalties, strengths


def _score_query_efficiency(
    query_count: int, operation_type: str = "general"
) -> tuple[float, List[str], List[str]]:
    """Score database query efficiency (0-40 points).

    Args:
        query_count: Number of database queries
        operation_type: Type of operation (affects scoring thresholds)

    Returns:
        Tuple of (score, penalties, strengths)
    """
    penalties = []
    strengths = []

    # Operation-specific scoring for DELETE operations
    if operation_type == "delete_view":
        # More lenient for DELETE due to cascade operations
        if query_count == 0:
            score = 35.0
            strengths.append("No database queries")
        elif query_count == 1:
            score = 40.0
            strengths.append("Single query deletion")
        elif query_count <= 3:
            score = 38.0
            strengths.append(f"Excellent for DELETE ({query_count} queries)")
        elif query_count <= 8:
            score = 35.0
            strengths.append(f"Very good for DELETE ({query_count} queries)")
        elif query_count <= 15:
            score = 28.0
            strengths.append(f"Good for DELETE ({query_count} queries)")
        elif query_count <= 25:
            score = 20.0
            penalties.append(f"Acceptable for DELETE ({query_count} queries)")
        elif query_count <= 35:
            score = 12.0
            penalties.append(f"Needs optimization ({query_count} queries)")
        elif query_count <= 50:
            score = 5.0
            penalties.append(f"Poor query efficiency ({query_count} queries)")
        else:
            score = 1.0
            penalties.append(f"Very poor query efficiency ({query_count} queries)")
    else:
        # Standard scoring for other operations
        if query_count == 0:
            score = 35.0
            strengths.append("No database queries (cached/static)")
        elif query_count == 1:
            score = 40.0
            strengths.append("Perfect - single query")
        elif query_count == 2:
            score = 38.0
            strengths.append("Excellent - minimal queries")
        elif query_count <= 3:
            score = 35.0
            strengths.append(f"Very good query efficiency ({query_count} queries)")
        elif query_count <= 6:
            score = 30.0
            strengths.append(f"Good query efficiency ({query_count} queries)")
        elif query_count <= 10:
            score = 20.0
            penalties.append(f"Acceptable query count ({query_count} queries)")
        elif query_count <= 15:
            score = 10.0
            penalties.append(f"Needs query optimization ({query_count} queries)")
        elif query_count <= 25:
            score = 3.0
            penalties.append(f"Poor query efficiency ({query_count} queries)")
        elif query_count <= 50:
            score = 1.0
            penalties.append(f"Very poor query efficiency ({query_count} queries)")
        else:
            score = 0.0
            penalties.append(f"Terrible query efficiency ({query_count} queries)")

    return score, penalties, strengths


def _score_memory_efficiency(memory_overhead_mb: float) -> tuple[float, List[str], List[str]]:
    """Score memory efficiency (0-20 points).

    Args:
        memory_overhead_mb: Memory overhead above baseline in MB

    Returns:
        Tuple of (score, penalties, strengths)
    """
    penalties = []
    strengths = []

    if memory_overhead_mb <= 5:
        score = 19.0
        strengths.append(f"Very efficient memory usage (+{memory_overhead_mb:.1f}MB)")
    elif memory_overhead_mb <= 15:
        score = 17.0
        strengths.append(f"Good memory efficiency (+{memory_overhead_mb:.1f}MB)")
    elif memory_overhead_mb <= 30:
        score = 14.0
        strengths.append(f"Acceptable memory overhead (+{memory_overhead_mb:.1f}MB)")
    elif memory_overhead_mb <= 50:
        score = 8.0
        penalties.append(f"High memory overhead (+{memory_overhead_mb:.1f}MB)")
    elif memory_overhead_mb <= 100:
        score = 3.0
        penalties.append(f"Very high memory overhead (+{memory_overhead_mb:.1f}MB)")
    else:
        score = 0.0
        penalties.append(f"Excessive memory overhead (+{memory_overhead_mb:.1f}MB)")

    return score, penalties, strengths


def score_performance(metrics: PerformanceMetrics) -> PerformanceScore:
    """Calculate comprehensive performance score.

    Args:
        metrics: PerformanceMetrics to score

    Returns:
        PerformanceScore with detailed breakdown

    Example:
        >>> metrics = PerformanceMetrics(response_time_ms=50, query_count=3, ...)
        >>> score = score_performance(metrics)
        >>> print(f"Grade: {score.grade} ({score.total_score:.1f}/100)")
        Grade: A (85.0/100)
    """
    all_penalties: List[str] = []
    all_strengths: List[str] = []

    # Score individual components
    response_score, resp_penalties, resp_strengths = _score_response_time(
        metrics.response_time_ms
    )
    all_penalties.extend(resp_penalties)
    all_strengths.extend(resp_strengths)

    query_score, query_penalties, query_strengths = _score_query_efficiency(
        metrics.query_count, metrics.operation_type
    )
    all_penalties.extend(query_penalties)
    all_strengths.extend(query_strengths)

    memory_score, mem_penalties, mem_strengths = _score_memory_efficiency(
        metrics.memory_overhead_mb
    )
    all_penalties.extend(mem_penalties)
    all_strengths.extend(mem_strengths)

    # Calculate total score
    total_score = response_score + query_score + memory_score

    # Ensure score is between 0-100
    total_score = max(0.0, min(100.0, total_score))

    # Calculate grade
    grade = _calculate_grade(total_score)

    return PerformanceScore(
        total_score=total_score,
        grade=grade,
        response_time_score=response_score,
        query_efficiency_score=query_score,
        memory_efficiency_score=memory_score,
        penalties=all_penalties,
        strengths=all_strengths,
    )
