"""Avrupa Patent Ofisi (EPO) şekli inceleme kuralları.

Rule 49 EPC (başvuru belgelerinin sunumu) ve EPC madde 78/84'e dayanır.
Tüm kurallar deterministiktir (LLM'siz). Ortak kurallar (istem
numaralandırma, tek cümle, özet uzunluğu) `rules.py`'de çalıştırılır;
bu modül yalnızca EPO'ya ÖZGÜ kontrolleri içerir.

Kaynak: Rule 49 EPC — General provisions governing the presentation of
the application documents.
"""

from __future__ import annotations

import re

from app.services.formality.models import Finding, Severity

_CLAIM_START = re.compile(r"^\s*(\d+)\s*[.)]\s+", re.MULTILINE)


def check_epo_abstract_present(abstract: str) -> list[Finding]:
    """EPC madde 78(1)(e): başvuruda özet (abstract) bulunması zorunludur."""
    if (abstract or "").strip():
        return []
    return [
        Finding(
            rule_id="epo.abstract_missing",
            severity=Severity.ERROR,
            section="ozet",
            title="Abstract is missing",
            detail=(
                "A European patent application must contain an abstract "
                "(EPC Art. 78(1)(e)). The abstract is required after the "
                "filing date even if not present at filing."
            ),
            suggestion="Add an abstract summarising the technical disclosure.",
            legal_basis="EPC Art. 78(1)(e)",
        )
    ]


def check_epo_claims_present(claims: str) -> list[Finding]:
    """EPC madde 78(1)(c): en az bir istem (claim) bulunmalıdır."""
    if _CLAIM_START.search(claims or ""):
        return []
    return [
        Finding(
            rule_id="epo.claims_missing",
            severity=Severity.ERROR,
            section="istemler",
            title="No claims found",
            detail=(
                "A European patent application must contain at least one "
                "claim (EPC Art. 78(1)(c)). No numbered claim was detected."
            ),
            suggestion="Add at least one numbered claim (1., 2., ...).",
            legal_basis="EPC Art. 78(1)(c)",
        )
    ]


def check_epo_abstract_length(abstract: str) -> list[Finding]:
    """Rule 47(3) EPC / PCT Rule 8: özet tercihen 150 kelimeyi aşmamalı."""
    words = len(re.findall(r"\S+", abstract or ""))
    if words <= 150:
        return []
    return [
        Finding(
            rule_id="epo.abstract_too_long",
            severity=Severity.WARNING,
            section="ozet",
            title=f"Abstract is too long ({words} words)",
            detail=(
                "The abstract should preferably not exceed 150 words "
                f"(Rule 47(3) EPC). The current abstract has {words} words."
            ),
            suggestion=f"Shorten the abstract by about {words - 150} words.",
            legal_basis="Rule 47(3) EPC",
        )
    ]


def check_epo_abstract_no_merit_language(abstract: str) -> list[Finding]:
    """Rule 47(2) EPC: özet, buluşun değer/üstünlük iddialarını içermemeli."""
    # İngilizce övgü/spekülasyon kalıpları — özet yalnızca teknik özet olmalı.
    merit_terms = [
        "advantage",
        "advantageous",
        "superior",
        "better than",
        "novel and",
        "improvement over",
        "best",
    ]
    low = (abstract or "").lower()
    hit = next((t for t in merit_terms if t in low), None)
    if not hit:
        return []
    return [
        Finding(
            rule_id="epo.abstract_merit_language",
            severity=Severity.WARNING,
            section="ozet",
            title="Abstract may contain merit/comparison language",
            detail=(
                "The abstract should not contain statements on the alleged "
                "merits or value of the invention (Rule 47(2) EPC). Found: "
                f"\"{hit}\"."
            ),
            suggestion=(
                "Rephrase the abstract as a neutral technical summary, "
                "without claims of advantage or comparison."
            ),
            excerpt=hit,
            legal_basis="Rule 47(2) EPC",
        )
    ]


def check_epo_rules(
    *,
    description: str = "",
    claims: str = "",
    abstract: str = "",
) -> list[Finding]:
    """Tüm EPO-özgü deterministik kuralları çalıştırır."""
    findings: list[Finding] = []
    findings += check_epo_abstract_present(abstract)
    findings += check_epo_claims_present(claims)
    findings += check_epo_abstract_length(abstract)
    findings += check_epo_abstract_no_merit_language(abstract)
    return findings
