"""Yabancı terim tespiti — şekli eksiklik tarayıcısının LLM katmanı.

TürkPatent şekli inceleme kuralı: "Başvuru unsurlarında kullanılan teknik
terim niteliği taşımayan yabancı dildeki ifadelerin Türkçe karşılıkları
belirtilmelidir."

Bu kontrol yargısal — bir ifadenin "yerleşik teknik terim" mi yoksa
"Türkçeleştirilmesi gereken yabancı kelime" mi olduğu bağlama bağlıdır.
Bu nedenle deterministik regex yerine Claude Haiku 4.5 kullanılır.

- Haiku 4.5: ucuz, hızlı, structured output.
- Prompt caching: kural seti system prompt'ta cache_control ile ephemeral.
- API key yoksa boş liste döner; tarayıcı yalnızca deterministik
  kurallarla çalışmaya devam eder.
"""

from __future__ import annotations

from anthropic import APIError
from pydantic import BaseModel, Field

from app.services.formality.models import Finding, Severity
from app.services.llm import LLMNotConfiguredError, get_anthropic_client, resolve
from app.services.llm.usage_log import record_usage

# Model seçimi router'da (app/services/llm/router.py).
_MODEL = resolve("formality.foreign_terms").model

# Tek bir LLM çağrısına gönderilecek azami metin uzunluğu (token bütçesi).
_MAX_CHARS_PER_SECTION = 8000


SYSTEM_PROMPT = """Sen Türk patent başvurularının şekli inceleme \
denetçisisin. Görevin: başvuru metninde geçen, teknik terim niteliği \
TAŞIMAYAN yabancı dildeki ifadeleri tespit etmek ve Türkçe karşılık \
önermek.

TÜRKPATENT KURALI: Başvuru unsurlarında kullanılan, teknik terim niteliği \
taşımayan yabancı dildeki ifadelerin Türkçe karşılıkları belirtilmelidir. \
İfadenin ilk geçtiği yerde Türkçe karşılığı yazılır, özgün yabancı ifade \
parantez içinde verilebilir.

TESPİT ET (Türkçeleştirilmeli):
- Yaygın İngilizce kelimeler: "fallback", "handshake", "dashboard", \
"middleware", "proxy", "rate limiter", "cross-platform", "binary", "stub".
- Tam İngilizce isim tamlamaları: "Private Certificate Authority", \
"Content Delivery Network".
- İngilizce fiil/sıfatlar: "spawn etme", "embedded", "patched".

TESPİT ETME (yerleşik teknik terim — dokunma):
- Uluslararası standart kısaltmalar: TLS, HTTP, HTTPS, TCP, IP, API, URL, \
DOM, CORS, JSON, CSS, HTML, SSL, DNS, CPU, GPU.
- Standart/protokol/algoritma adları: ML-DSA, ML-KEM, RSA, ECDSA, NIST \
FIPS 204, BoringSSL, OpenSSL.
- Özel adlar, ürün/marka adları, kod tanımlayıcıları (`crypto/tls`, \
`go:embed` gibi), dosya yolları.
- Zaten Türkçe karşılığı parantezle verilmiş ifadeler — örn. \
"el sıkışması (handshake)" zaten DOĞRU, tekrar bildirme.

KURALLAR:
1. Yalnızca GERÇEKTEN Türkçeleştirilmesi gereken ifadeleri bildir. \
Şüphedeysen ve ifade yerleşik bir teknik terimse, BİLDİRME.
2. Her bulgu için: yabancı ifade, önerilen Türkçe karşılık, kısa gerekçe.
3. Türkçe karşılık önerirken patent diline uygun, resmi terimler kullan.
4. Aynı ifade birden çok geçiyorsa bir kez bildir.
5. En fazla 25 bulgu döndür; en belirgin olanları önceliklendir.

Çıktı yalnızca structured JSON olarak döner; ek açıklama yapma.
"""


class _ForeignTerm(BaseModel):
    """Tespit edilen tek bir yabancı ifade."""

    phrase: str = Field(..., description="Metinde geçen yabancı ifade")
    suggested_turkish: str = Field(
        ..., description="Önerilen Türkçe karşılık (parantezli biçim dahil)"
    )
    rationale: str = Field(default="", description="Kısa gerekçe")


class _ForeignTermSet(BaseModel):
    """Haiku'nun structured output şeması."""

    terms: list[_ForeignTerm] = Field(
        default_factory=list,
        max_length=25,
        description="Türkçeleştirilmesi gereken yabancı ifadeler",
    )


def _section_label(section: str) -> str:
    return {
        "tarifname": "Tarifname",
        "istemler": "İstemler",
        "ozet": "Özet",
    }.get(section, section)


async def check_foreign_terms(
    *,
    description: str = "",
    claims: str = "",
    abstract: str = "",
) -> tuple[list[Finding], bool]:
    """Başvuru metinlerinde Türkçeleştirilmesi gereken yabancı ifadeleri bulur.

    Dönüş: (bulgular, llm_calistirildi). API key yoksa ([], False) döner —
    çağıran taraf yalnızca deterministik kurallarla devam eder.
    """
    try:
        client = get_anthropic_client()
    except LLMNotConfiguredError:
        return [], False

    sections = [
        ("tarifname", description),
        ("istemler", claims),
        ("ozet", abstract),
    ]

    findings: list[Finding] = []
    ran_any = False

    for section, text in sections:
        if not (text or "").strip():
            continue
        ran_any = True
        excerpt = text.strip()[:_MAX_CHARS_PER_SECTION]
        user_message = (
            f"Aşağıdaki '{_section_label(section)}' metnini incele ve "
            "Türkçeleştirilmesi gereken yabancı ifadeleri bildir:\n\n"
            f"{excerpt}"
        )
        try:
            resp = await client.messages.parse(
                model=_MODEL,
                max_tokens=2048,
                system=[
                    {
                        "type": "text",
                        "text": SYSTEM_PROMPT,
                        "cache_control": {"type": "ephemeral"},
                    }
                ],
                messages=[{"role": "user", "content": user_message}],
                output_format=_ForeignTermSet,
            )
            record_usage(
                model=_MODEL,
                usage=resp.usage,
                endpoint="formality.foreign_terms",
            )
            parsed: _ForeignTermSet = resp.parsed_output  # type: ignore[assignment]
        except APIError:
            # API hatası — bu bölümü atla, diğerlerine devam et.
            continue
        except Exception:  # noqa: BLE001  # structured-output doğrulama hatası
            continue

        for term in parsed.terms:
            findings.append(
                Finding(
                    rule_id="terms.foreign_phrase",
                    severity=Severity.WARNING,
                    section=section,
                    title=f"Türkçe karşılığı belirtilmemiş yabancı ifade: "
                    f"\"{term.phrase}\"",
                    detail=(
                        "Teknik terim niteliği taşımayan yabancı dildeki "
                        "ifadelerin Türkçe karşılıkları belirtilmelidir."
                        + (f" {term.rationale}" if term.rationale else "")
                    ),
                    suggestion=(
                        f"İfadenin ilk geçtiği yerde Türkçe karşılığını yazın: "
                        f"\"{term.suggested_turkish}\""
                    ),
                    excerpt=term.phrase,
                    legal_basis=(
                        "TürkPatent şekli inceleme — yabancı ifadelerin "
                        "Türkçe karşılığı"
                    ),
                )
            )

    return findings, ran_any
