"""Simple boilerplate detection for document chunks.

Returns a 0.0-1.0 score indicating how likely a chunk is boilerplate.
Does NOT delete chunks — only marks them for downstream filtering decisions.
"""

from __future__ import annotations

import re

# Common boilerplate patterns in financial documents
_BOILERPLATE_PATTERNS: list[tuple[re.Pattern[str], float]] = [
    # Forward-looking statements disclaimer
    (re.compile(
        r"forward[- ]looking\s+statements?",
        re.IGNORECASE,
    ), 0.4),
    # Safe harbor language
    (re.compile(
        r"safe\s+harbor",
        re.IGNORECASE,
    ), 0.3),
    # Copyright notices
    (re.compile(
        r"(?:©|\bcopyright\b)\s*\d{4}",
        re.IGNORECASE,
    ), 0.3),
    # All rights reserved
    (re.compile(
        r"all\s+rights\s+reserved",
        re.IGNORECASE,
    ), 0.2),
    # Disclaimer language
    (re.compile(
        r"\b(?:disclaimer|disclaims?)\b",
        re.IGNORECASE,
    ), 0.2),
    # "This press release" meta-reference
    (re.compile(
        r"this\s+(?:press\s+release|report|document)\s+(?:contains?|includes?|may\s+contain)",
        re.IGNORECASE,
    ), 0.2),
    # Not an offer/solicitation language
    (re.compile(
        r"(?:not|does\s+not)\s+constitute\s+(?:an?\s+)?(?:offer|solicitation|recommendation)",
        re.IGNORECASE,
    ), 0.3),
    # Boilerplate risk factors intro
    (re.compile(
        r"(?:actual\s+results|future\s+results)\s+(?:may|could|might)\s+differ\s+materially",
        re.IGNORECASE,
    ), 0.3),
    # Contact/investor relations boilerplate
    (re.compile(
        r"(?:investor\s+relations?|media\s+(?:contact|inquiries))\s*:",
        re.IGNORECASE,
    ), 0.2),
    # Legal entity registrations
    (re.compile(
        r"registered\s+(?:in|under)\s+(?:the\s+)?(?:laws?\s+of|state\s+of)",
        re.IGNORECASE,
    ), 0.15),
]

# If the chunk is mostly short lines (like a signature block), boost score
_SHORT_LINE_THRESHOLD = 40
_SHORT_LINE_RATIO_THRESHOLD = 0.7


def score_boilerplate(text: str) -> float:
    """Score a text chunk for boilerplate content.

    Returns a float between 0.0 (not boilerplate) and 1.0 (definitely boilerplate).
    The score is the sum of matched pattern weights, capped at 1.0.
    """
    if not text.strip():
        return 0.0

    score = 0.0

    # Check pattern matches
    for pattern, weight in _BOILERPLATE_PATTERNS:
        if pattern.search(text):
            score += weight

    # Check for signature-block-like structure (many short lines)
    lines = text.split("\n")
    if lines:
        short_lines = sum(1 for line in lines if 0 < len(line.strip()) <= _SHORT_LINE_THRESHOLD)
        non_empty = sum(1 for line in lines if line.strip())
        if non_empty > 3 and short_lines / non_empty > _SHORT_LINE_RATIO_THRESHOLD:
            score += 0.15

    return min(score, 1.0)
