"""FastAPI: bullet notes → polished business email via Claude Sonnet 4."""
import json
import logging
import os
from typing import Literal

from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
from openai import AsyncOpenAI
from pydantic import BaseModel, Field

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

app = FastAPI(title="Email Drafter")
app.add_middleware(CORSMiddleware, allow_origins=["*"],
                   allow_methods=["*"], allow_headers=["*"])

MODEL = os.getenv("LLM_MODEL", "anthropic/claude-sonnet-4-20250514")
_client: AsyncOpenAI | None = None


def _get_client() -> AsyncOpenAI:
    global _client
    if _client is None:
        _client = AsyncOpenAI(
            base_url=os.getenv("LITELLM_BASE_URL", "http://host.docker.internal:4000/v1"),
            api_key=os.getenv("LITELLM_API_KEY", "sk-dummy"),
        )
    return _client


class GenerateRequest(BaseModel):
    notes: str = Field(..., min_length=1, max_length=4000)
    recipient: str = ""
    signature: str = ""
    tone: Literal["formal", "friendly", "firm", "apologetic"] = "formal"
    language: Literal["cs", "en"] = "cs"
    reply_to: str = ""  # Optional original email being replied to


TONE_HINTS = {
    "formal":     {"cs": "formální, oficiální, profesionální",
                   "en": "formal, professional, polite"},
    "friendly":   {"cs": "přátelský, vstřícný, kolegiální",
                   "en": "friendly, warm, collegial"},
    "firm":       {"cs": "důrazný, asertivní, věcný, ale zdvořilý",
                   "en": "firm, assertive, direct yet polite"},
    "apologetic": {"cs": "omluvný, smířlivý, akceptující odpovědnost",
                   "en": "apologetic, conciliatory, owning responsibility"},
}


def _system_prompt(language: str, tone: str) -> str:
    tone_hint = TONE_HINTS[tone][language]
    if language == "cs":
        return f"""Jste asistent píšící obchodní e-maily v češtině.

Vstupem jsou poznámky / odrážky od pisatele. Z nich vytvoříte uhlazený, profesionální e-mail.

Tón: {tone_hint}.

Vraťte POUZE platný JSON v tomto tvaru, žádné markdown obaly:
{{
  "subject": "Předmět e-mailu (krátký, výstižný, do 70 znaků)",
  "body": "Tělo e-mailu včetně oslovení na začátku a podpisu na konci. Použijte odstavce oddělené prázdným řádkem."
}}

Pravidla:
- Pište v 1. osobě jednotného čísla (jako pisatel sám)
- Oslovení voľte podle kontextu příjemce (Vážený pane / Ahoj / atd.)
- Pokud vstup obsahuje žádost, zformulujte ji jasně a zdvořile
- Nevymýšlejte si fakta, která nejsou ve vstupu
- Pokud je dodán podpis, použijte ho doslovně. Jinak ukončete obecným podpisem typu „S pozdravem,\\nVaše jméno"
- Pokud je dodán původní e-mail (reply_to), navažte na něj — odkažte na to, co píše"""
    else:
        return f"""You are an assistant writing business emails in English.

The input is bullet notes from the writer. Turn them into a polished, professional email.

Tone: {tone_hint}.

Return ONLY valid JSON in this shape, no markdown wrappers:
{{
  "subject": "Email subject (short, to the point, under 70 chars)",
  "body": "Email body including greeting at top and signature at end. Use paragraphs separated by blank lines."
}}

Rules:
- Write in first person (as the sender)
- Choose greeting based on recipient context (Dear / Hi / Hello)
- If input contains a request, phrase it clearly and politely
- Do not invent facts not in the input
- If a signature is provided, use it verbatim. Otherwise end with a generic "Best regards,\\nYour name"
- If an original email is provided (reply_to), reference it appropriately"""


@app.get("/")
async def root():
    return FileResponse("static/index.html")


@app.post("/api/generate")
async def generate(req: GenerateRequest):
    user_parts = [f"POZNÁMKY PISATELE / WRITER NOTES:\n{req.notes.strip()}"]
    if req.recipient.strip():
        user_parts.append(f"\nPŘÍJEMCE / RECIPIENT:\n{req.recipient.strip()}")
    if req.signature.strip():
        user_parts.append(f"\nPODPIS / SIGNATURE:\n{req.signature.strip()}")
    if req.reply_to.strip():
        user_parts.append(
            f"\nPŮVODNÍ E-MAIL (pro reply) / ORIGINAL EMAIL TO REPLY TO:\n{req.reply_to.strip()}"
        )

    try:
        resp = await _get_client().chat.completions.create(
            model=MODEL,
            messages=[
                {"role": "system", "content": _system_prompt(req.language, req.tone)},
                {"role": "user", "content": "\n".join(user_parts)},
            ],
            temperature=0.3,
            max_tokens=2000,
        )
    except Exception as exc:
        logger.exception("LLM call failed")
        raise HTTPException(500, f"Generování selhalo: {exc}")

    raw = (resp.choices[0].message.content or "").strip()
    raw = raw.removeprefix("```json").removeprefix("```").removesuffix("```").strip()
    try:
        data = json.loads(raw)
    except json.JSONDecodeError as exc:
        logger.error("JSON parse failed: %s\nraw=%s", exc, raw[:500])
        raise HTTPException(500, "Nepodařilo se zpracovat odpověď AI")

    return {
        "subject": data.get("subject", "").strip(),
        "body": data.get("body", "").strip(),
    }


@app.get("/health")
async def health():
    return {"status": "ok"}


app.mount("/static", StaticFiles(directory="static"), name="static")
