"""Intake form'u için AI destekli chip önerileri.

Kullanıcı buluş anlatımı formunun herhangi bir sorusunu açtığında, daha önce
doldurduğu cevapları + sorunun bağlamını Claude Haiku 4.5'a gönderiyoruz ve
o soruya özel 10-12 chip önerisi alıyoruz.

Özellikler:
- Claude Haiku 4.5 (ucuz, hızlı; tek çağrı ~400-800ms, ~$0.001)
- Prompt caching: system prompt (soru kataloğu + format) cache_control ile
  ephemeral → tekrar çağrılarda token maliyeti ~0.1x
- Structured output: messages.parse() + Pydantic IntakeSuggestionSet
- Fallback: Claude yanıt vermezse veya API key yoksa boş liste döneriz,
  frontend statik default chip'lere düşer
"""

from __future__ import annotations

from anthropic import APIError
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel, Field

from app.services.llm import (
    LLMNotConfiguredError,
    get_anthropic_client,
)

router = APIRouter(prefix="/intake", tags=["intake"])

# Sorunun id'si → kullanıcıya gösterilen Türkçe başlık + Claude'a açıklama
# (static questions.ts'in aynısıyla tutarlı olmalı)
QUESTION_META: dict[str, dict[str, str]] = {
    "technical_field": {
        "title": "Teknik alan",
        "purpose": "Buluşun hangi teknik sınıfa girdiğini belirten kategoriler (IPC-benzeri). Örn: 'Kriptografi', 'Robotik', 'Biyoteknoloji'.",
    },
    "problem": {
        "title": "Çözülen problem",
        "purpose": "Mevcut sistemlerin eksiklerini gösteren problem kategorileri. Örn: 'Düşük performans', 'Yetersiz güvenlik', 'Yüksek enerji tüketimi'.",
    },
    "prior_art": {
        "title": "Önceki çözümler",
        "purpose": "Önceki tekniğin durumunu gösteren yaklaşım tipleri. Örn: 'Standartlaşmış çözüm var', 'Akademik makaleler mevcut', 'Ticari ürün rakip'.",
    },
    "advantages": {
        "title": "Teknik avantajlar",
        "purpose": "Ölçülebilir, patent istemini destekleyen avantaj tipleri. Örn: 'Daha düşük gecikme', 'Daha yüksek güvenlik', 'Donanımdan bağımsız'.",
    },
    "industrial_applicability": {
        "title": "Endüstriyel uygulama alanı",
        "purpose": "Buluşun kullanılabileceği sektörler. Örn: 'Bankacılık', 'Sağlık', 'Savunma', 'Enerji'.",
    },
}


class IntakeSuggestionRequest(BaseModel):
    """Frontend → backend isteği."""

    question_id: str = Field(..., description="Hangi soru için öneri?")
    # Daha önce doldurulmuş cevaplar (boşlar da dahil). Bağlam için gerekli.
    context: dict[str, str] = Field(
        default_factory=dict,
        description="Şimdiye kadar doldurulmuş intake cevapları",
    )
    # Proje başlığı bağlam için yardımcı
    title: str | None = Field(default=None, max_length=200)
    jurisdiction: str = Field(default="TR", pattern=r"^(TR|EP|US|PCT)$")


class IntakeSuggestionSet(BaseModel):
    """Claude'dan dönen structured output."""

    suggestions: list[str] = Field(
        ...,
        min_length=6,
        max_length=14,
        description="6-14 arası kısa chip label'ı (her biri 2-6 kelime, Türkçe)",
    )


class IntakeSuggestionResponse(BaseModel):
    """Frontend'e döndürdüğümüz yanıt."""

    question_id: str
    suggestions: list[str]
    source: str = Field(description="'ai' veya 'fallback' veya 'unsupported'")
    model: str | None = None


SYSTEM_PROMPT = """Sen Türk patent vekillerinin buluş anlatımı formunu \
doldurmalarına yardım eden bir asistansın. Görevin: verilen projeye özel, \
kısa, seçilebilir öneri chip'leri üretmek.

KURAL­LAR:
1. Tek Türkçe chip başına 2-6 kelime. Daha uzun yazma.
2. Chip'ler projenin teknik alanına UYGUN olmalı — örneğin biyoteknoloji \
projesinde "Kriptografi" önerme.
3. Chip'ler BİRBİRİNİ TEKRARLA­MAMALI — farklı açılardan bak.
4. Soru'ya özel odak: eğer soru "problem" hakkındaysa sadece problem \
kategorileri ver; "avantajlar" ise avantaj sloganları ver.
5. 8-12 arası chip ver (min 6, max 14).
6. Emoji KULLANMA. Numara da ekleme. Her chip tek satır, plain text.
7. Türk patent vekili jargoniyle uyumlu dil kullan (resmi, teknik, kısa).

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


class IntakeDraftAnswerRequest(BaseModel):
    """Bir sorunun cevabını AI ile doldur/geliştir."""

    question_id: str = Field(..., description="Hangi soru için cevap üret?")
    question_title: str = Field(..., description="Sorunun başlığı (context için)")
    question_hint: str = Field(
        default="", description="Sorunun rehber açıklaması (context için)"
    )
    current_text: str = Field(
        default="",
        max_length=8000,
        description="Kullanıcının şu ana kadar yazdığı metin (varsa geliştir, yoksa yeni yaz)",
    )
    context: dict[str, str] = Field(
        default_factory=dict,
        description="Diğer soruların cevapları — bağlam için",
    )
    title: str | None = Field(default=None, max_length=200)
    jurisdiction: str = Field(default="TR", pattern=r"^(TR|EP|US|PCT)$")
    min_length: int = Field(default=40, ge=10, le=2000)


class IntakeDraftAnswerResponse(BaseModel):
    """Üretilen cevap."""

    question_id: str
    answer: str
    mode: str = Field(description="'generated' veya 'improved' veya 'fallback'")
    model: str | None = None


DRAFT_ANSWER_SYSTEM_PROMPT = """Sen Türk patent vekillerinin buluş anlatımı \
formunu doldurmalarına yardım eden bir asistansın. Görevin: bir sorunun \
cevabını, vekilin DAHA ÖNCE doldurduğu diğer cevaplara uyumlu şekilde, \
taslak olarak yazmak.

KURAL­LAR:
1. Türkçe yaz. Resmi, teknik, patent-vekil jargonu.
2. Yanıt min_length karakterden uzun ama gereksiz uzatma; 3-6 cümle \
veya 5-10 madde yeterli.
3. Diğer sorulardaki bilgilerle ÇELİŞME. Tutarlı ol.
4. Vekilin zaten yazdığı text varsa (current_text boş değilse), onu \
TAMAMEN YENİDEN YAZMA — sadece daha iyi ifade et, eksikleri tamamla, \
teknik dil yükselt. Kısaltma.
5. Vekilin seçtiği chip'ler (•, ▸ işaretli satırlar) varsa onları koru \
ve genişlet.
6. Emoji, markdown başlık, code block KULLANMA. Sadece düz Türkçe metin \
(gerekiyorsa bullet listesi olarak).
7. "Taslak", "lütfen doldurun" gibi meta ifadeler YAZMA — direkt cevabı ver.
8. Spesifik rakamlar (~%40 daha hızlı, <10ms gecikme) uydurma — onları \
vekilin doldurması gerekir; generic "yüksek hız sağlar" ifadesi kullan.
9. İstem (claim) yazma — bu bir intake formu, istem daha sonra ayrı üretilir.

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


@router.post("/suggestions")
async def intake_suggestions(req: IntakeSuggestionRequest) -> IntakeSuggestionResponse:
    """Bağlama göre chip önerileri üret."""
    meta = QUESTION_META.get(req.question_id)
    if not meta:
        # Bu soru için AI önerisi desteklenmiyor (solution/novelty/variations
        # gibi özgür-metin ağırlıklı sorular) — frontend statik default'lara
        # düşsün
        return IntakeSuggestionResponse(
            question_id=req.question_id,
            suggestions=[],
            source="unsupported",
        )

    try:
        client = get_anthropic_client()
    except LLMNotConfiguredError:
        return IntakeSuggestionResponse(
            question_id=req.question_id,
            suggestions=[],
            source="fallback",
        )

    # Kullanıcı mesajı — projenin bağlamı
    ctx_lines: list[str] = []
    if req.title:
        ctx_lines.append(f"Proje başlığı: {req.title}")
    ctx_lines.append(f"Hedef patent ofisi: {req.jurisdiction}")
    ctx_lines.append("")
    ctx_lines.append("Şimdiye kadar vekilin doldurduğu cevaplar:")
    filled_any = False
    for k, v in (req.context or {}).items():
        if v and v.strip():
            filled_any = True
            # Çok uzun cevapları kısalt (prompt budget)
            excerpt = v.strip()[:400]
            ctx_lines.append(f"  • {k}: {excerpt}")
    if not filled_any:
        ctx_lines.append("  (henüz hiçbir soru doldurulmadı)")
    ctx_lines.append("")
    ctx_lines.append(
        f'Şimdi "{meta["title"]}" sorusu için chip önerileri üret. '
        f"Bu soru şu amaçla: {meta['purpose']}"
    )
    if filled_any:
        ctx_lines.append(
            "\nCHIPS'LER YUKARIDAKİ CEVAPLARLA UYUMLU VE TAMAMLAYICI OLMALI — "
            "aynı projenin devamıymış gibi."
        )
    user_message = "\n".join(ctx_lines)

    try:
        resp = await client.messages.parse(
            model="claude-haiku-4-5",
            max_tokens=1024,
            system=[
                {
                    "type": "text",
                    "text": SYSTEM_PROMPT,
                    "cache_control": {"type": "ephemeral"},
                }
            ],
            messages=[{"role": "user", "content": user_message}],
            response_format=IntakeSuggestionSet,
        )
        parsed: IntakeSuggestionSet = resp.output_parsed  # type: ignore[assignment]
        return IntakeSuggestionResponse(
            question_id=req.question_id,
            suggestions=parsed.suggestions,
            source="ai",
            model="claude-haiku-4-5",
        )
    except APIError as e:
        # API hatası (rate limit, auth, vs.) — fallback'e düş
        raise HTTPException(status_code=502, detail=f"Anthropic API error: {e}") from e
    except Exception as e:  # noqa: BLE001  # structured output validation da buraya düşer
        raise HTTPException(
            status_code=500, detail=f"Suggestion generation failed: {e}"
        ) from e


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

    answer: str = Field(..., min_length=10, max_length=4000)


@router.post("/draft-answer")
async def intake_draft_answer(
    req: IntakeDraftAnswerRequest,
) -> IntakeDraftAnswerResponse:
    """Bir soru için taslak cevap üret / mevcut metni geliştir."""
    try:
        client = get_anthropic_client()
    except LLMNotConfiguredError:
        return IntakeDraftAnswerResponse(
            question_id=req.question_id,
            answer="",
            mode="fallback",
        )

    mode = "improved" if req.current_text.strip() else "generated"

    ctx_lines: list[str] = []
    if req.title:
        ctx_lines.append(f"Proje başlığı: {req.title}")
    ctx_lines.append(f"Hedef patent ofisi: {req.jurisdiction}")
    ctx_lines.append("")
    ctx_lines.append("Vekilin doldurduğu diğer cevaplar:")
    filled_any = False
    for k, v in (req.context or {}).items():
        if k == req.question_id:
            continue
        if v and v.strip():
            filled_any = True
            excerpt = v.strip()[:500]
            ctx_lines.append(f"  • {k}: {excerpt}")
    if not filled_any:
        ctx_lines.append("  (diğer sorular henüz doldurulmadı)")
    ctx_lines.append("")
    ctx_lines.append(f'Şu anki soru: "{req.question_title}"')
    if req.question_hint:
        ctx_lines.append(f"Açıklama: {req.question_hint}")
    ctx_lines.append(f"Hedef minimum uzunluk: ~{req.min_length} karakter")
    ctx_lines.append("")

    if req.current_text.strip():
        ctx_lines.append(
            "Vekil şu metni başlamış (chip seçimleri dahil). Bunu GELİŞTİR, "
            "tamamla, teknik dili yükselt. Chip satırlarını (• veya ▸ ile "
            "başlayan) koru:"
        )
        ctx_lines.append("```")
        ctx_lines.append(req.current_text[:6000])
        ctx_lines.append("```")
    else:
        ctx_lines.append(
            "Vekil bu soruya henüz bir şey yazmadı. Diğer cevaplardan yola "
            "çıkarak proje bağlamına uygun bir TASLAK cevap yaz."
        )

    user_message = "\n".join(ctx_lines)

    try:
        resp = await client.messages.parse(
            model="claude-haiku-4-5",
            max_tokens=1500,
            system=[
                {
                    "type": "text",
                    "text": DRAFT_ANSWER_SYSTEM_PROMPT,
                    "cache_control": {"type": "ephemeral"},
                }
            ],
            messages=[{"role": "user", "content": user_message}],
            response_format=_DraftAnswerPayload,
        )
        parsed: _DraftAnswerPayload = resp.output_parsed  # type: ignore[assignment]
        return IntakeDraftAnswerResponse(
            question_id=req.question_id,
            answer=parsed.answer.strip(),
            mode=mode,
            model="claude-haiku-4-5",
        )
    except APIError as e:
        raise HTTPException(status_code=502, detail=f"Anthropic API error: {e}") from e
    except Exception as e:  # noqa: BLE001
        raise HTTPException(
            status_code=500, detail=f"Draft answer failed: {e}"
        ) from e
