from dataclasses import dataclass
from typing import Dict, Optional


@dataclass
class ESGScore:
    supplier_id: str
    score: float
    rationale: str


def weighted_esg_score(
    supplier_id: str,
    factors: Dict[str, float],
    weights: Optional[Dict[str, float]] = None,
) -> ESGScore:
    if not factors:
        return ESGScore(supplier_id=supplier_id, score=0.0, rationale="No ESG factors provided.")

    if weights is None:
        weights = {k: 1.0 for k in factors.keys()}

    total_weight = 0.0
    total_score = 0.0
    for key, value in factors.items():
        weight = float(weights.get(key, 1.0))
        total_weight += weight
        total_score += weight * float(value)

    normalized = (total_score / total_weight) if total_weight > 0 else 0.0
    score = max(0.0, min(100.0, normalized * 100.0))
    rationale = "Weighted ESG score from normalized factors: " + ", ".join(
        f"{k}={v:.2f}" for k, v in factors.items()
    )
    return ESGScore(supplier_id=supplier_id, score=score, rationale=rationale)
