"""Hızlı 2-yönlü çeviri yardımcıları — TR ↔ EN, prior-art akışı için.

Tasarım:
- Dil tespiti heuristik (TR karakterler) — LLM çağırmadan ucuz/hızlı
- Çeviri Claude Haiku 4.5; structured output zorla, kısa kalıp
- Hit çevirisi BATCH — tek istek, paralel hit'ler. 10x ucuz.

Hatalar yutulmaz değil ama None döner — çağıran kodun fallback davranışı
prior-art aramasını engellemeden devam etmek (orijinal dilde göster).
"""

from __future__ import annotations

import logging
import re

from anthropic import APIError
from pydantic import BaseModel, Field

from app.services.llm import LLMNotConfiguredError, get_anthropic_client
from app.services.llm.usage_log import record_usage

logger = logging.getLogger(__name__)

# Türkçe diakritik karakterleri tespit için regex
_TR_CHARS = re.compile(r"[ıİşŞğĞçÇüÜöÖ]")


def detect_language(text: str) -> str:
    """Çok kaba dil tespiti: 'tr' veya 'en'.

    - Türkçe karakter varsa → 'tr'
    - Aksi halde → 'en' (varsayılan; Almanca/Fransızca gibi diller de
      EN'e fall back; pratikte vekiller TR veya EN yazar)
    """
    if not text:
        return "en"
    if _TR_CHARS.search(text):
        return "tr"
    return "en"


# ---------------------------------------------------------------------------
# Query çevirisi (kısa metin, tek seferlik)
# ---------------------------------------------------------------------------


class _QueryTranslation(BaseModel):
    """Bir patent arama sorgusunun TR↔EN çevirisi."""

    translated: str = Field(
        ...,
        description="Hedef dile çevrilmiş sorgu — kısa, anahtar kelime ağırlıklı, "
        "patent terminolojisinde",
    )


_QUERY_SYSTEM = """\
Sen bir patent arama sorgusunu Türkçe ↔ İngilizce arasında çeviren bir
asistansın. Çeviride:

1. Patent terminolojisini koru (örn. "buluş" → "invention", "tertibat" →
   "apparatus", "yöntem" → "method").
2. Anlam değiştirme; kelime kelime değil ama anlam birebir.
3. Kısa tut — orijinalin uzunluğu kadar veya biraz daha az.
4. Marka/kısaltmaları olduğu gibi bırak (TLS, AI, IoT vs).
5. Hedef dilde yaygın patent araması terimlerini kullan.
6. Sadece çevrilmiş sorguyu döndür.
"""


async def translate_query(text: str, target_lang: str) -> str | None:
    """Bir patent arama sorgusunu hedef dile çevir.

    target_lang: 'tr' veya 'en'

    Returns:
        Çevrilmiş metin veya None (LLM yapılandırılmamışsa / hata)
    """
    if not text.strip():
        return None
    try:
        client = get_anthropic_client()
    except LLMNotConfiguredError:
        return None

    direction = "İngilizceye" if target_lang == "en" else "Türkçeye"
    user_msg = (
        f"Aşağıdaki patent arama sorgusunu {direction} çevir:\n\n"
        f"```\n{text}\n```"
    )
    try:
        resp = await client.messages.parse(
            model="claude-haiku-4-5",
            max_tokens=200,
            system=[
                {
                    "type": "text",
                    "text": _QUERY_SYSTEM,
                    "cache_control": {"type": "ephemeral"},
                }
            ],
            messages=[{"role": "user", "content": user_msg}],
            output_format=_QueryTranslation,
        )
        record_usage(
            model="claude-haiku-4-5",
            usage=resp.usage,
            endpoint="translation.query",
        )
        parsed: _QueryTranslation | None = resp.parsed_output  # type: ignore[assignment]
        return parsed.translated.strip() if parsed else None
    except APIError as exc:
        logger.warning("Query translation failed: %s", exc)
        return None
    except Exception as exc:  # noqa: BLE001
        logger.warning("Query translation unexpected error: %s", exc)
        return None


# ---------------------------------------------------------------------------
# Hit çevirisi (batch, çoklu hit tek istekte)
# ---------------------------------------------------------------------------


class _TranslatedHit(BaseModel):
    """Bir hit'in çevirilen alanları."""

    index: int = Field(..., description="0-based sıra; hangi hit olduğunu belirler")
    title: str = Field(default="")
    abstract: str = Field(default="")


class _BatchHitTranslation(BaseModel):
    """Birden fazla hit'in toplu çevirisi."""

    items: list[_TranslatedHit] = Field(default_factory=list)


_HIT_SYSTEM = """\
Sen patent başlıkları ve özetlerini Türkçeye çeviren bir asistansın.

Kurallar:
1. Patent terminolojisini Türkçe karşılığıyla koru ("apparatus" → "tertibat",
   "method" → "yöntem", "system" → "sistem", "device" → "cihaz" vs).
2. Marka/kısaltmaları olduğu gibi bırak (örn. TLS, IoT, RFID).
3. Anlam birebir; gereksiz Türkçeleştirme yapma.
4. Resmi, teknik, vekil dilinde — günlük dil değil.
5. Boş/None gelirse boş string döndür.
6. Index numarasını koru; hit sırasını karıştırma.

Çıktı: structured JSON, açıklama veya markdown EKLEME.
"""


async def translate_hits_to_tr(
    items: list[tuple[str | None, str | None]],
) -> list[tuple[str | None, str | None]] | None:
    """Birden fazla (title, abstract) çiftini Türkçeye çevir.

    Args:
        items: [(title, abstract), ...] — None'lar boş string olarak çevrilir

    Returns:
        Aynı uzunlukta liste, [(tr_title, tr_abstract), ...]
        None döner: LLM yapılandırılmamış veya hata.
    """
    if not items:
        return []
    try:
        client = get_anthropic_client()
    except LLMNotConfiguredError:
        return None

    # Numaralı listeyi user message'da hazırla
    numbered = []
    for i, (title, abstract) in enumerate(items):
        t = (title or "").strip()
        a = (abstract or "").strip()
        # Abstract çok uzun olursa kısalt — vekile özet yeter, full abstract
        # external link'te zaten var. Token tasarrufu.
        if len(a) > 600:
            a = a[:600] + "…"
        numbered.append(f"### Hit {i}\n**Title:** {t}\n**Abstract:** {a}")
    user_msg = (
        "Aşağıdaki patent hit'lerini Türkçeye çevir. Her hit için index, "
        "title ve abstract döndür.\n\n" + "\n\n".join(numbered)
    )

    try:
        resp = await client.messages.parse(
            model="claude-haiku-4-5",
            max_tokens=3000,
            system=[
                {
                    "type": "text",
                    "text": _HIT_SYSTEM,
                    "cache_control": {"type": "ephemeral"},
                }
            ],
            messages=[{"role": "user", "content": user_msg}],
            output_format=_BatchHitTranslation,
        )
        record_usage(
            model="claude-haiku-4-5",
            usage=resp.usage,
            endpoint="translation.hits",
        )
        parsed: _BatchHitTranslation | None = resp.parsed_output  # type: ignore[assignment]
        if not parsed:
            return None
        # Index → çeviri map'i (sıra bozulabilir LLM tarafından)
        by_index = {x.index: (x.title or None, x.abstract or None) for x in parsed.items}
        # Orijinal sıraya göre döndür; eksikse (None, None)
        return [by_index.get(i, (None, None)) for i in range(len(items))]
    except APIError as exc:
        logger.warning("Hit translation failed: %s", exc)
        return None
    except Exception as exc:  # noqa: BLE001
        logger.warning("Hit translation unexpected error: %s", exc)
        return None
