# backend/app/services/mail_ai.py
# 아리 메일 분석. 기존 ai_json 재사용 + 신규 메일은 실 LLM(휴리스틱 폴백 없음, phase-16+).
from sqlmodel import Session

from ..llm.provider import LLMProvider
from ..models import Email

ANALYZE_SCHEMA = {
    "type": "object",
    "properties": {
        "summary": {"type": "string"},
        "priority": {"type": "string", "enum": ["높음", "보통", "낮음"]},
        "category": {"type": "string"},
        "tasks": {"type": "array", "items": {"type": "object"}},
        "events": {"type": "array", "items": {"type": "object"}},
        "replies": {"type": "array", "items": {"type": "object"}},
        "file": {"type": ["object", "null"]},
    },
    "required": ["summary", "priority", "category"],
}

ANALYZE_PROMPT = """당신은 한국어 비서 '아리'입니다. 아래 이메일을 읽고 JSON 으로만 답하세요.
실제로 사용자가 해야 할 행동이 있을 때만 tasks/events/replies 를 채우고, 없으면 빈 배열로 두세요.
광고·뉴스레터·자동알림은 보통 priority=낮음 이고 tasks/events 가 비어 있을 수 있어요.

반드시 아래 필드명을 그대로 사용하세요(다른 이름 금지):
- summary: 한 줄 요약(한국어)
- priority: "높음" | "보통" | "낮음"
- category: 짧은 분류 라벨(예: 검토 요청, 마감 임박, 영수증, 결제/금융, 뉴스레터)
- tasks: [{{"text": 할 일 문장, "project": 분류, "due": "MM/DD" 또는 "", "prio": "높음|보통|낮음"}}]
- events: [{{"title": 제목, "date": "MM/DD", "day": 요일, "time": "HH:MM", "place": 장소}}]
- replies: [{{"tone": 한 줄 의도, "preview": 미리보기, "body": 보낼 본문 전체}}]
- file: {{"project": 분류, "reason": 사유}} 또는 null

제목: {subject}
보낸 사람: {sender}
본문:
{body}
"""


def _s(v) -> str:
    return v if isinstance(v, str) else ("" if v is None else str(v))


def _coerce_analysis(d: dict) -> dict:
    """모델 출력의 필드명 흔들림을 우리 스키마로 정규화(text/title 등 별칭 흡수)."""
    prio = _s(d.get("priority")).strip()
    if prio not in ("높음", "보통", "낮음"):
        prio = "보통"
    tasks = []
    for t in d.get("tasks") or []:
        if not isinstance(t, dict):
            continue
        text = _s(t.get("text") or t.get("title") or t.get("task") or t.get("name")).strip()
        if not text:
            continue
        tasks.append(
            {
                "text": text,
                "project": _s(t.get("project") or t.get("category") or "메일"),
                "due": _s(t.get("due") or t.get("due_date") or t.get("deadline")),
                "prio": _s(t.get("prio") or t.get("priority") or "보통") or "보통",
            }
        )
    events = []
    for e in d.get("events") or []:
        if not isinstance(e, dict):
            continue
        title = _s(e.get("title") or e.get("summary") or e.get("name")).strip()
        if not title:
            continue
        events.append(
            {
                "title": title,
                "date": _s(e.get("date") or e.get("start_date")),
                "day": _s(e.get("day") or e.get("weekday")),
                "time": _s(e.get("time") or e.get("start") or e.get("start_time")),
                "dur": _s(e.get("dur") or e.get("duration")),
                "place": _s(e.get("place") or e.get("location")),
            }
        )
    replies = []
    for r in d.get("replies") or []:
        if not isinstance(r, dict):
            continue
        body = _s(r.get("body") or r.get("content") or r.get("text")).strip()
        if not body:
            continue
        replies.append(
            {
                "tone": _s(r.get("tone") or r.get("intent") or "정중한 답장"),
                "preview": _s(r.get("preview") or body[:60]),
                "body": body,
            }
        )
    file = None
    f = d.get("file")
    if isinstance(f, dict) and (f.get("project") or f.get("reason")):
        file = {"project": _s(f.get("project") or "메일"), "reason": _s(f.get("reason"))}
    return {
        "summary": _s(d.get("summary")).strip(),
        "priority": prio,
        "category": _s(d.get("category")).strip() or "메일",
        "tasks": tasks,
        "events": events,
        "replies": replies,
        "file": file,
    }


def analyze_email(s: Session, email: Email, provider: LLMProvider) -> dict:
    """신규/재분석용. 이미 분석된 메일은 ai_json 재사용, 신규는 실 LLM(폴백 없음)."""
    if email.ai_json:
        return email.ai_json
    prompt = ANALYZE_PROMPT.format(
        subject=email.subject, sender=email.from_key, body="\n".join(email.body or [])[:4000]
    )
    raw = provider.generate_json(prompt, ANALYZE_SCHEMA)  # LLM 미가용 시 예외 전파
    result = _coerce_analysis(raw)
    email.ai_json = result
    s.add(email)
    s.commit()
    return result
