from __future__ import annotations

import re


POSITIVE_TERMS = {
    "breakthrough",
    "progress",
    "improve",
    "improves",
    "improved",
    "solution",
    "solutions",
    "recovery",
    "restore",
    "restores",
    "rescued",
    "rescue",
    "volunteer",
    "community",
    "donate",
    "donation",
    "cure",
    "treatment",
    "therapy",
    "clean energy",
    "renewable",
    "conservation",
    "protect",
    "protects",
    "restoration",
    "kindness",
    "hope",
    "first",
    "record",
}

AGENCY_TERMS = {
    "how",
    "helps",
    "helping",
    "protect",
    "protects",
    "builds",
    "creates",
    "launches",
    "teaches",
    "learn",
    "guide",
    "tool",
    "program",
    "initiative",
    "effort",
    "plan",
    "rebuild",
}

CORTISOL_TERMS = {
    "war",
    "killed",
    "dead",
    "death",
    "murder",
    "shooting",
    "attack",
    "crisis",
    "catastrophe",
    "disaster",
    "collapse",
    "panic",
    "warning",
    "threat",
    "fear",
    "fears",
    "lawsuit",
    "scandal",
}

RAGEBAIT_TERMS = {
    "slams",
    "blasts",
    "furious",
    "outrage",
    "rage",
    "shocking",
    "you won't believe",
    "sparks backlash",
    "destroyed",
    "humiliates",
}

PR_TERMS = {
    "announces",
    "unveils",
    "funding round",
    "raises",
    "partnership",
    "brand",
    "sponsored",
    "press release",
}

WORD_RE = re.compile(r"[a-z0-9']+")


def _count_terms(text: str, terms: set[str]) -> int:
    lowered = text.lower()
    words = set(WORD_RE.findall(lowered))
    count = 0
    for term in terms:
        if " " in term:
            count += 1 if term in lowered else 0
        elif term in words:
            count += 1
    return count


def score_article(title: str, description: str | None, source_pr_risk: int) -> dict:
    text = f"{title}. {description or ''}"
    positive = _count_terms(text, POSITIVE_TERMS)
    agency = _count_terms(text, AGENCY_TERMS)
    cortisol = _count_terms(text, CORTISOL_TERMS)
    ragebait = _count_terms(text, RAGEBAIT_TERMS)
    pr_terms = _count_terms(text, PR_TERMS)

    constructive_score = min(10, 2 + positive * 2 + agency)
    agency_score = min(10, 1 + agency * 2)
    cortisol_score = min(10, cortisol * 3)
    ragebait_score = min(10, ragebait * 4)
    pr_risk_score = min(10, source_pr_risk + pr_terms * 2)
    human_benefit_score = min(10, positive * 2 + agency)
    novelty_score = 5

    accepted = (
        constructive_score >= 5
        and cortisol_score <= 5
        and ragebait_score <= 3
        and pr_risk_score <= 7
    )

    if accepted:
        reason_code = "heuristic_constructive_candidate"
        reason_text = "Constructive or agency-oriented language with low obvious cortisol/ragebait signals."
    elif ragebait_score > 3:
        reason_code = "heuristic_reject_ragebait_language"
        reason_text = "Headline or snippet contains outrage-oriented language."
    elif cortisol_score > 5:
        reason_code = "heuristic_reject_cortisol_heavy"
        reason_text = "Headline or snippet appears tragedy, threat, conflict, or crisis centered."
    elif pr_risk_score > 7:
        reason_code = "heuristic_reject_pr_risk"
        reason_text = "Headline or source has signs of corporate PR framing."
    else:
        reason_code = "heuristic_needs_review"
        reason_text = "Not enough constructive signal for automatic acceptance."

    return {
        "constructive_score": constructive_score,
        "cortisol_score": cortisol_score,
        "ragebait_score": ragebait_score,
        "agency_score": agency_score,
        "human_benefit_score": human_benefit_score,
        "novelty_score": novelty_score,
        "pr_risk_score": pr_risk_score,
        "accepted": 1 if accepted else 0,
        "reason_code": reason_code,
        "reason_text": reason_text,
        "model_name": "heuristic-v0",
    }
