"""
generate-web-desc endpoint
POST /api/product-desc/generate-web-desc

Pipeline:
  Phase 1 — Vision  (Llama 4 Scout): nhìn ảnh → extract thông tin thô
  Phase 2 — Writer  (GPT-OSS 120B) : viết mô tả marketing chuẩn cho web
  → Trả về JSON gồm: mo_ta_web, mo_ta_ngan, dac_diem_noi_bat, huong_dan_bao_quan
"""

import logging
from typing import Optional

from fastapi import APIRouter
from fastapi.responses import JSONResponse
from pydantic import BaseModel

# Re-use helpers đã có sẵn trong file gốc
# from .ultra_desc_route import _call_ai_with_fallback, _fetch_image_base64, _extract_json, VISION_MODEL, ENRICH_MODEL

logger = logging.getLogger(__name__)

# ─── Nếu paste riêng file này thì dùng block dưới ──────────────────────────
# (Nếu merge vào file gốc thì xoá phần này đi vì đã có rồi)
import asyncio
import base64
import json
import re

import httpx

GROQ_API_KEYS = [
    "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",
    "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",
    "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",
    "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",
    "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",
    "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",
]
_groq_idx = 0
VISION_MODEL = "meta-llama/llama-4-scout-17b-16e-instruct"
ENRICH_MODEL = "openai/gpt-oss-120b"


def _next_key():
    global _groq_idx
    key = GROQ_API_KEYS[_groq_idx % len(GROQ_API_KEYS)]
    _groq_idx += 1
    return key


async def _fetch_image_base64(url: str) -> str:
    async with httpx.AsyncClient(timeout=15) as c:
        r = await c.get(url, headers={"User-Agent": "Mozilla/5.0"})
        r.raise_for_status()
        return base64.b64encode(r.content).decode()


def _extract_json(raw) -> dict | None:
    if isinstance(raw, dict):
        return raw
    if not isinstance(raw, str):
        raw = str(raw)
    if "```" in raw:
        m = re.search(r'```(?:json)?\s*([\s\S]*?)```', raw)
        if m:
            try:
                return json.loads(m.group(1).strip())
            except Exception:
                pass
    m = re.search(r'\{[\s\S]*\}', raw)
    if m:
        try:
            return json.loads(m.group(0))
        except Exception:
            pass
    try:
        return json.loads(raw.strip())
    except Exception:
        return None


async def _groq_call(messages: list, model: str, max_tokens: int = 2000) -> str:
    """Round-robin Groq call, thử hết key trước khi đổi model."""
    fallbacks = [model]
    if model != "openai/gpt-oss-120b":
        fallbacks.append("openai/gpt-oss-120b")
    if model != "openai/gpt-oss-20b":
        fallbacks.append("openai/gpt-oss-20b")

    while True:
        for m in fallbacks:
            for _ in range(len(GROQ_API_KEYS)):
                key = _next_key()
                try:
                    async with httpx.AsyncClient(timeout=30) as c:
                        resp = await c.post(
                            "https://api.groq.com/openai/v1/chat/completions",
                            headers={"Authorization": f"Bearer {key}", "Content-Type": "application/json"},
                            json={"model": m, "max_tokens": max_tokens, "temperature": 0.7, "messages": messages},
                        )
                    if resp.status_code == 200:
                        data = resp.json()
                        if "error" not in data:
                            return data["choices"][0]["message"]["content"]
                    elif resp.status_code == 429:
                        continue  # rotate key ngay
                    else:
                        break  # lỗi khác → thử model tiếp
                except Exception as e:
                    logger.warning(f"Groq error ({m}): {e}")
                    break
        logger.warning("All keys/models exhausted → wait 5s")
        await asyncio.sleep(5)
# ─── Hết phần re-use ────────────────────────────────────────────────────────


# ─── Router ─────────────────────────────────────────────────────────────────
router = APIRouter(prefix="/api/product-desc", tags=["Ultra Description"])


# ─── Request Schema ──────────────────────────────────────────────────────────
class WebDescRequest(BaseModel):
    # Bắt buộc
    ma_san_pham: str
    ten_san_pham: str
    image_url: str
    # Nên có
    chat_lieu: Optional[str] = None
    # Optional — từ Sheets
    mo_ta_chung: Optional[str] = None
    thanh_phan: Optional[str] = None
    form: Optional[str] = None
    hoan_canh: Optional[str] = None
    dong_san_pham: Optional[str] = None
    gioi_tinh: Optional[str] = None
    featuring: Optional[str] = None
    tinh_nang: Optional[str] = None
    chung_chi: Optional[str] = None
    huong_dan_su_dung: Optional[str] = None


# ─── Phase 1 Prompt — Vision ─────────────────────────────────────────────────
def _build_vision_prompt(req: WebDescRequest) -> str:
    """Llama 4 Scout nhìn ảnh, extract thông tin thô làm nền cho writer."""
    extra = []
    if req.chat_lieu:
        extra.append(f"- Chất liệu (đã biết, KHÔNG đoán lại): {req.chat_lieu}")
    if req.form:
        extra.append(f"- Form dáng: {req.form}")
    if req.tinh_nang:
        extra.append(f"- Tính năng vải: {req.tinh_nang}")
    if req.hoan_canh:
        extra.append(f"- Dịp mặc mong muốn: {req.hoan_canh}")
    if req.featuring:
        extra.append(f"- Điểm nhấn thiết kế: {req.featuring}")
    if req.chung_chi:
        extra.append(f"- Chứng chỉ: {req.chung_chi}")
    if req.gioi_tinh:
        extra.append(f"- Giới tính: {req.gioi_tinh}")

    extra_block = "\n".join(extra) if extra else "Không có thông tin bổ sung."

    return f"""Bạn là chuyên gia phân tích sản phẩm thời trang Canifa.
Nhìn ảnh sản phẩm và kết hợp thông tin đã biết để trả về JSON sau:

THÔNG TIN ĐÃ BIẾT:
- Tên SP: {req.ten_san_pham}
{extra_block}

QUAN TRỌNG:
- Nếu đã có chất liệu → DÙNG NGUYÊN, không đoán lại
- Nếu không có chất liệu → ghi "Theo thông tin nhà sản xuất"
- Chỉ nhận xét những gì THẤY ĐƯỢC trong ảnh

Trả về JSON (không text thừa):
{{
  "mau_sac_chinh": "Màu sắc chính nhìn thấy trong ảnh",
  "form_dang": "Form dáng (Slim/Regular/Oversize/...)",
  "dac_trung_thiet_ke": "2-3 đặc trưng thiết kế nổi bật",
  "chat_lieu_vision": "Chất liệu (dùng thông tin đã biết nếu có)",
  "tinh_nang_vai": "Tính năng vải nổi bật",
  "phu_hop_dip": "2-3 dịp mặc phù hợp nhìn từ ảnh",
  "phong_cach": "Phong cách tổng thể (1-3 từ khóa)",
  "doi_tuong": "Đối tượng phù hợp",
  "diem_manh": "Điểm mạnh nổi bật nhất của sản phẩm"
}}"""


# ─── Phase 2 Prompt — Writer ─────────────────────────────────────────────────
def _build_writer_prompt(req: WebDescRequest, vision_data: dict) -> str:
    """GPT-OSS 120B viết mô tả marketing hoàn chỉnh cho web."""

    # Ưu tiên: chat_lieu từ Sheets > vision > fallback
    final_material = (
        req.chat_lieu
        or vision_data.get("chat_lieu_vision", "")
        or "Theo thông tin nhà sản xuất"
    )

    # Tổng hợp context đầy đủ
    context_parts = [
        f"Tên SP: {req.ten_san_pham}",
        f"Chất liệu: {final_material}",
        f"Form dáng: {req.form or vision_data.get('form_dang', 'Không xác định')}",
        f"Màu sắc: {vision_data.get('mau_sac_chinh', '')}",
        f"Đặc trưng thiết kế: {vision_data.get('dac_trung_thiet_ke', '')}",
        f"Tính năng vải: {req.tinh_nang or vision_data.get('tinh_nang_vai', '')}",
        f"Dịp mặc: {req.hoan_canh or vision_data.get('phu_hop_dip', '')}",
        f"Phong cách: {vision_data.get('phong_cach', '')}",
        f"Đối tượng: {vision_data.get('doi_tuong', '')}",
    ]
    if req.featuring:
        context_parts.append(f"Featuring: {req.featuring}")
    if req.chung_chi:
        context_parts.append(f"Chứng chỉ: {req.chung_chi}")
    if req.mo_ta_chung:
        context_parts.append(f"Mô tả gốc (cần enrich): {req.mo_ta_chung}")
    if req.huong_dan_su_dung:
        context_parts.append(f"Hướng dẫn bảo quản: {req.huong_dan_su_dung}")

    context_block = "\n".join(f"- {p}" for p in context_parts)

    return f"""Bạn là Stylist cao cấp Canifa. Viết mô tả sản phẩm cho website bán hàng.

THÔNG TIN SẢN PHẨM:
{context_block}

QUY TẮC VIẾT:
- Giọng văn: tự tin, gợi hình, dùng từ như "hack dáng", "tôn dáng", "thoát dáng"
- KHÔNG bịa chất liệu nếu không chắc — dùng đúng thông tin đã có
- KHÔNG đề cập giá cả
- Viết cho KHÁCH HÀNG đọc (không phải AI)
- mo_ta_web: 3-5 câu, có story, có benefit rõ ràng
- mo_ta_ngan: 1 câu súc tích cho meta description / preview card

Trả về JSON (không text thừa):
{{
  "mo_ta_web": "Mô tả đầy đủ 3-5 câu cho trang web",
  "mo_ta_ngan": "1 câu ngắn cho preview/meta (~120 ký tự)",
  "dac_diem_noi_bat": [
    "Điểm nổi bật 1 (chất liệu / tính năng)",
    "Điểm nổi bật 2 (form / thiết kế)",
    "Điểm nổi bật 3 (dịp mặc / đối tượng)"
  ],
  "huong_dan_bao_quan": "Hướng dẫn giặt và bảo quản cụ thể"
}}"""


# ─── Endpoint ────────────────────────────────────────────────────────────────
@router.post("/generate-web-desc", summary="Sinh mô tả web cho SP mới (chưa cần có trong DB)")
async def generate_web_desc(req: WebDescRequest):
    """
    Pipeline 2 pha:
      1. Vision  → extract thông tin từ ảnh
      2. Writer  → viết mô tả marketing cho web
    Không cần SP có trong StarRocks/DB.
    """
    import time
    t0 = time.time()

    try:
        # ── Phase 1: Vision ──────────────────────────────────────────────────
        logger.info(f"[generate-web-desc] {req.ma_san_pham} — Phase 1: Vision")

        try:
            img_b64 = await _fetch_image_base64(req.image_url)
            vision_messages = [
                {
                    "role": "user",
                    "content": [
                        {
                            "type": "image_url",
                            "image_url": {"url": f"data:image/jpeg;base64,{img_b64}"},
                        },
                        {"type": "text", "text": _build_vision_prompt(req)},
                    ],
                }
            ]
            vision_raw = await _groq_call(vision_messages, VISION_MODEL, max_tokens=800)
            vision_data = _extract_json(vision_raw) or {}
        except Exception as vision_err:
            # Vision lỗi (ảnh không load được...) → vẫn chạy tiếp với data rỗng
            logger.warning(f"[generate-web-desc] Vision failed: {vision_err}. Continuing without vision data.")
            vision_data = {}

        logger.info(f"[generate-web-desc] {req.ma_san_pham} — Phase 1 done: {vision_data}")

        # ── Phase 2: Writer ──────────────────────────────────────────────────
        logger.info(f"[generate-web-desc] {req.ma_san_pham} — Phase 2: Writer")

        writer_messages = [
            {
                "role": "system",
                "content": (
                    "Bạn là Stylist cao cấp Canifa. Viết mô tả sản phẩm thời trang bằng tiếng Việt. "
                    "Phong cách: tự tin, gợi hình, không bịa chất liệu, không đề cập giá cả. "
                    "Luôn trả về JSON chuẩn, không text thừa."
                ),
            },
            {"role": "user", "content": _build_writer_prompt(req, vision_data)},
        ]

        writer_raw = await _groq_call(writer_messages, ENRICH_MODEL, max_tokens=1200)
        result = _extract_json(writer_raw)

        if not result:
            return JSONResponse(
                status_code=500,
                content={
                    "status": "error",
                    "ma_san_pham": req.ma_san_pham,
                    "message": "AI writer không trả về JSON hợp lệ.",
                    "raw": writer_raw[:500] if writer_raw else None,
                },
            )

        # ── Đảm bảo output có đủ 4 trường cơ bản ───────────────────────────
        result.setdefault("mo_ta_web", "")
        result.setdefault("mo_ta_ngan", "")
        result.setdefault("dac_diem_noi_bat", [])
        result.setdefault("huong_dan_bao_quan", req.huong_dan_su_dung or "")

        elapsed = round(time.time() - t0, 2)
        logger.info(f"[generate-web-desc] {req.ma_san_pham} — Done in {elapsed}s")

        return {
            "status": "success",
            "ma_san_pham": req.ma_san_pham,
            "ten_san_pham": req.ten_san_pham,
            # ── 4 trường output chính ──
            "mo_ta_web": result["mo_ta_web"],
            "mo_ta_ngan": result["mo_ta_ngan"],
            "dac_diem_noi_bat": result["dac_diem_noi_bat"],
            "huong_dan_bao_quan": result["huong_dan_bao_quan"],
            # ── Debug info ──
            "elapsed_s": elapsed,
            "vision_data": vision_data,  # optional: xoá dòng này nếu không cần debug
        }

    except Exception as e:
        logger.exception(f"[generate-web-desc] Unhandled error: {e}")
        return JSONResponse(
            status_code=500,
            content={"status": "error", "ma_san_pham": req.ma_san_pham, "message": str(e)},
        )
