"""Claude로 10페이지 카드 카피를 한 번에 생성."""

import json
import logging
import re
from typing import Any, Dict, Optional

from anthropic import Anthropic

from .config import ANTHROPIC_API_KEY, ANTHROPIC_MODEL_SONNET
from . import db

logger = logging.getLogger(__name__)

DEFAULT_ACCENT_BY_CATEGORY = {
    "economy": "#0F62FE",
    "psychology": "#A66CFF",
    "celebrity": "#FF5C8A",
}

DEFAULT_PROMPT = """너는 인스타그램 카드 뉴스 카피라이터다.
카테고리: {category}
키워드: {keyword}
참고 기사:
{articles}

10페이지 인스타 카드용 카피를 다음 JSON 한 객체로만 출력해라 (코드펜스 금지):
{{
  "cover_copy": {{"headline": "<훅 한 줄>", "body": "<서브카피 1~2줄>", "accent_color": "#hex"}},
  "body_copies": [
    {{"headline": "<포인트 헤드라인>", "body": "<2~4문장 본문>"}},
    ... (총 8개)
  ],
  "cta_copy": {{"headline": "<요약 한 줄>", "body": "<마무리 1~2줄>", "cta": "팔로우/저장 등"}},
  "suggested_caption": "<인스타 캡션 본문>",
  "hashtags": ["#태그1", "#태그2", ...]
}}

[글자수 제약 — 카드 디자인 박스에 맞게 반드시 준수]
- cover_copy.headline: 22자 이내
- body_copies[].headline: 26자 이내
- body_copies[].body: 120자 이내 (2~4문장)
- cta_copy.headline: 22자 이내
초과하면 잘리므로 간결하고 임팩트 있게 작성한다.
"""


def _client() -> Anthropic:
    return Anthropic(api_key=ANTHROPIC_API_KEY)


def _strip_codefence(s: str) -> str:
    s = s.strip()
    if s.startswith("```"):
        s = re.sub(r"^```(?:json)?\s*|\s*```$", "", s).strip()
    return s


def _load_prompt() -> str:
    pt = db.get_prompt_template("slate_writer")
    if pt and pt.get("template"):
        return pt["template"]
    return DEFAULT_PROMPT


def write_slate(keyword: str, category: str,
                articles: Optional[list] = None) -> int:
    """Claude로 10페이지 카피 생성 후 card_slates에 저장. slate_id 반환."""
    if articles is None:
        articles = db.list_news_articles(category=category, days=2)
    article_text = "\n".join(
        f"- {a['title']}: {a.get('summary', '')[:120]}" for a in articles[:8]
    ) or "(참고 기사 없음)"

    prompt = _load_prompt().format(category=category, keyword=keyword, articles=article_text)
    msg = _client().messages.create(
        model=ANTHROPIC_MODEL_SONNET,
        max_tokens=4000,
        messages=[{"role": "user", "content": prompt}],
    )
    raw = msg.content[0].text
    cleaned = _strip_codefence(raw)
    try:
        data: Dict[str, Any] = json.loads(cleaned)
    except json.JSONDecodeError as e:
        logger.warning("slate JSON parse failed: %s", e)
        raise ValueError(f"Invalid JSON from LLM: {e}") from e

    body_copies = data.get("body_copies") or []
    if len(body_copies) != 8:
        raise ValueError(f"body_copies must have 8 items, got {len(body_copies)}")

    cover = data.get("cover_copy") or {}
    if not cover.get("accent_color"):
        cover["accent_color"] = DEFAULT_ACCENT_BY_CATEGORY.get(category, "#222831")

    sid = db.add_card_slate({
        "keyword": keyword,
        "category": category,
        "status": "draft",
        "cover_copy": cover,
        "body_copies": body_copies,
        "cta_copy": data.get("cta_copy") or {},
        "suggested_caption": data.get("suggested_caption") or "",
        "hashtags": data.get("hashtags") or [],
    })
    return sid
