"""
Chatbot V2 — Embedding + Vector Search + LLM Response
Flow: User hỏi → Embedding (OpenAI) → Vector Search DB → LLM viết response.
Chỉ 1 embedding call + 1 LLM call. Nhanh hơn nhiều so với 2 LLM call.
"""
import logging
import time

from common.embedding_service import create_embedding_async
from common.llm_factory import create_llm
from common.starrocks_connection import get_db_connection

logger = logging.getLogger(__name__)

MODEL_NAME = "gemini-3.1-flash-lite-preview"

RESPONSE_SYSTEM_PROMPT = """Bạn là AI Stylist của CANIFA — tư vấn thời trang nhiệt tình, tự nhiên.

QUY TẮC:
1. Dựa vào data sản phẩm thật từ DB để trả lời. CẤM BỊA thông tin SP.
2. Mỗi SP: nói tên, mã [SKU], giá (nếu đang sale thì gạch giá gốc), gợi ý dịp mặc.
3. ĐƯỢC gợi ý thêm: phù hợp dịp gì (đi làm, đi chơi...), phối với gì.
4. CẤM bịa chi tiết SP (chất liệu, form...) nếu data không có.
5. Tối đa 1-2 emoji. Giọng tự nhiên, thân thiện.
6. Cuối response: hỏi thêm nhu cầu hoặc gợi ý size.
7. Nếu không có SP → nói thật, gợi ý tìm tiêu chí khác.
"""


# ============================================================
# Helpers
# ============================================================
def _get_llm():
    return create_llm(MODEL_NAME, streaming=False, json_mode=False)


def _extract_text(content) -> str:
    """Extract text from Gemini response.content (có thể là str hoặc list)."""
    if isinstance(content, str):
        return content.strip()
    if isinstance(content, list):
        parts = []
        for part in content:
            if isinstance(part, str):
                parts.append(part)
            elif hasattr(part, "text"):
                parts.append(part.text)
            elif isinstance(part, dict) and "text" in part:
                parts.append(part["text"])
        return "\n".join(parts).strip()
    return str(content).strip()


# ============================================================
# Step 1: Embed user question (OpenAI ~200ms)
# ============================================================
async def embed_question(question: str) -> list[float]:
    """Embed câu hỏi bằng OpenAI text-embedding-3-small."""
    vector = await create_embedding_async(question)
    logger.info("📐 [V2] Embedded question: %d dims", len(vector))
    return vector


# ============================================================
# Step 2: Vector search DB (~200ms)
# ============================================================
async def vector_search(vector: list[float], limit: int = 30) -> list[dict]:
    """Vector search trên StarRocks dùng approx_cosine_similarity."""
    db = get_db_connection()
    if not db:
        raise Exception("DB connection failed")

    v_str = "[" + ",".join(str(x) for x in vector) + "]"

    sql = f"""
    WITH vector_matches AS (
        SELECT
            magento_ref_code,
            product_name,
            master_color,
            product_image_url_thumbnail,
            product_web_url,
            sale_price,
            original_price,
            discount_amount,
            ROUND(((original_price - sale_price) / original_price * 100), 0) as discount_percent,
            gender_by_product,
            age_by_product,
            product_line_vn,
            description_text,
            size_scale,
            quantity_sold,
            is_new_product,
            approx_cosine_similarity(vector, {v_str}) as similarity_score
        FROM shared_source.magento_product_dimension_with_text_embedding
        ORDER BY similarity_score DESC
        LIMIT {limit * 3}
    )
    SELECT *
    FROM vector_matches
    WHERE similarity_score > 0.3
    ORDER BY similarity_score DESC
    LIMIT {limit}
    """

    products = await db.execute_query_async(sql)
    logger.info("📊 [V2] Vector search returned %d products", len(products))
    return products


# ============================================================
# Step 3: LLM viết response (~2s)
# ============================================================
async def generate_response(user_question: str, products: list[dict]) -> str:
    """LLM viết response bán hàng từ data thực."""
    llm = _get_llm()

    if not products:
        product_info = "KHÔNG TÌM THẤY SẢN PHẨM NÀO."
    else:
        items = []
        for p in products[:10]:
            price_info = f"{int(p.get('sale_price', 0)):,}đ"
            if p.get("original_price") and p["original_price"] > p.get("sale_price", 0):
                price_info = f"~~{int(p['original_price']):,}đ~~ → {price_info}"
                if p.get("discount_percent"):
                    price_info += f" (-{int(p['discount_percent'])}%)"

            items.append(
                f"- [{p.get('magento_ref_code', '?')}] {p.get('product_name', '?')} | "
                f"Màu: {p.get('master_color', '?')} | Giá: {price_info} | "
                f"Size: {p.get('size_scale', '?')} | "
                f"Đã bán: {p.get('quantity_sold', 0)} | "
                f"Score: {p.get('similarity_score', 0):.3f} | "
                f"Mô tả: {(p.get('description_text') or '')[:100]}"
            )
        product_info = "\n".join(items)

    messages = [
        {"role": "system", "content": RESPONSE_SYSTEM_PROMPT},
        {
            "role": "user",
            "content": f"Câu hỏi khách: {user_question}\n\nDữ liệu SP từ DB:\n{product_info}\n\nViết response tư vấn:",
        },
    ]
    response = await llm.ainvoke(messages)
    return _extract_text(response.content)


# ============================================================
# Full flow: Question → Embed → Vector Search → LLM Response
# ============================================================
async def text_to_sql_chat(user_question: str) -> dict:
    """
    Full pipeline V2:
    1. Embed câu hỏi (OpenAI ~200ms)
    2. Vector search DB (~200ms)
    3. LLM viết response (~2s)
    Total target: ~2.5s
    """
    total_start = time.time()

    # Step 1: Embed
    embed_start = time.time()
    vector = await embed_question(user_question)
    embed_ms = (time.time() - embed_start) * 1000

    # Step 2: Vector search
    db_start = time.time()
    try:
        products = await vector_search(vector, limit=30)
    except Exception as e:
        logger.error("❌ [V2] Vector search failed: %s", e)
        products = []
    db_ms = (time.time() - db_start) * 1000

    # Step 3: Generate response
    resp_start = time.time()
    ai_response = await generate_response(user_question, products)
    resp_ms = (time.time() - resp_start) * 1000

    total_ms = (time.time() - total_start) * 1000

    logger.info(
        "✅ [V2] Done: %d products, embed=%.0fms, db=%.0fms, resp=%.0fms, total=%.0fms",
        len(products),
        embed_ms,
        db_ms,
        resp_ms,
        total_ms,
    )

    return {
        "ai_response": ai_response,
        "products": products,  # All products for frontend panel
        "sql": f"[Vector Search] Embedded '{user_question[:50]}' → cosine similarity top {len(products)}",
        "timing": {
            "embedding_ms": round(embed_ms),
            "db_search_ms": round(db_ms),
            "response_generation_ms": round(resp_ms),
            "total_ms": round(total_ms),
        },
        "product_count": len(products),
    }
