"""Risk Scoring Engine.

Combines detection signals from injection, secret, and PII modules
into a unified risk score with configurable weights and thresholds.
"""

from __future__ import annotations

from dataclasses import dataclass
from enum import Enum
from typing import Optional


class RiskLevel(str, Enum):
    """Discrete risk level."""

    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"

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


@dataclass
class RiskWeights:
    """Configurable weights for risk calculation.

    Default formula:
        risk_score = (injection * 0.4) + (secret * 0.3) + (pii * 0.2) + (entropy * 0.1)
    """

    injection: float = 0.4
    secret: float = 0.3
    pii: float = 0.2
    entropy: float = 0.1

    def __post_init__(self) -> None:
        total = self.injection + self.secret + self.pii + self.entropy
        if abs(total - 1.0) > 1e-6:
            # Normalise so weights always sum to 1
            self.injection /= total
            self.secret /= total
            self.pii /= total
            self.entropy /= total


@dataclass
class RiskThresholds:
    """Configurable thresholds for risk classification."""

    low_max: float = 0.3
    high_min: float = 0.7

    def classify(self, score: float) -> RiskLevel:
        if score < self.low_max:
            return RiskLevel.LOW
        if score > self.high_min:
            return RiskLevel.HIGH
        return RiskLevel.MEDIUM


class RiskScorer:
    """Combines detection signals into a unified risk score."""

    def __init__(
        self,
        weights: Optional[RiskWeights] = None,
        thresholds: Optional[RiskThresholds] = None,
    ) -> None:
        self.weights = weights or RiskWeights()
        self.thresholds = thresholds or RiskThresholds()

    def compute(
        self,
        injection_score: float = 0.0,
        secret_score: float = 0.0,
        pii_score: float = 0.0,
        entropy_score: float = 0.0,
    ) -> tuple[float, RiskLevel]:
        """Compute the weighted risk score and classify it.

        Parameters
        ----------
        injection_score : float
            Score from the injection detector (0-1).
        secret_score : float
            Score from the secret detector (0-1).
        pii_score : float
            Score from the PII detector (0-1).
        entropy_score : float
            Raw entropy score normalised to 0-1.

        Returns
        -------
        tuple[float, RiskLevel]
            The composite risk score and its classified level.
        """
        score = (
            injection_score * self.weights.injection
            + secret_score * self.weights.secret
            + pii_score * self.weights.pii
            + entropy_score * self.weights.entropy
        )
        score = round(min(1.0, max(0.0, score)), 4)
        level = self.thresholds.classify(score)
        return score, level
