"""
CANIFA Data Retrieval Tool - Tối giản cho Agentic Workflow.
Hỗ trợ Hybrid Search: Semantic (Vector) + Metadata Filter.
"""

import asyncio
import json
import logging
import time

from langfuse import observe

from langchain_core.tools import tool
from pydantic import BaseModel, Field


from agent.helper import format_product_results
from agent.tools.product_search_helpers import build_starrocks_query
from common.starrocks_connection import get_db_connection

# Setup Logger
logger = logging.getLogger(__name__)

from agent.prompt_utils import read_tool_prompt


class SearchItem(BaseModel):
    model_config = {"extra": "forbid"}  # STRICT MODE

    # ====== SEMANTIC SEARCH ======
    description: str = Field(
        description=(
            "Mô tả sản phẩm cho semantic search. "
            "FORMAT: 'product_name: [tên]. description_text: [mô tả]. "
            "material_group: [chất liệu]. style: [phong cách]. fitting: [dáng]. "
            "form_sleeve: [tay]. form_neckline: [cổ]. product_line_vn: [dòng SP]'. "
            "🚨 product_name = CHÍNH XÁC lời user nói, TUYỆT ĐỐI KHÔNG tự đổi sang tên khác. "
            "VD: user nói 'áo ngọ nguậy' → product_name: Áo ngọ nguậy (KHÔNG đổi thành 'Áo phông'!). "
            "VD: user nói 'áo cá sấu' → product_name: Áo cá sấu (KHÔNG đổi!). "
            "Chỉ chuẩn hóa từ đồng nghĩa RÕ RÀNG: 'áo thun'→'Áo phông', 'quần bò'→'Quần jean'. "
            "⚠️ KHÔNG đưa master_color vào description — dùng field master_color riêng! "
            "product_line_vn trong description = broad category (Áo phông, Áo Polo, Quần jean...). "
            "VD: 'áo ngọ nguậy' → 'product_name: Áo ngọ nguậy. product_line_vn: Áo phông'. "
            "VD: 'áo cá sấu polo' → 'product_name: Áo cá sấu polo. product_line_vn: Áo Polo'."
        )
    )
    product_name: str | None = Field(
        description="Tên sản phẩm. Chỉ điền khi khách cung cấp tên cụ thể.",
    )

    # ====== SKU LOOKUP ======
    magento_ref_code: str | None = Field(
        description="Mã sản phẩm chính xác (SKU). Chỉ điền khi khách cung cấp mã cụ thể.",
    )

    # ====== SQL HARD FILTERS (lọc trực tiếp trong DB query) ======
    gender_by_product: str | None = Field(
        description="[SQL FILTER] Giới tính. GIÁ TRỊ HỢP LỆ: women, men, boy, girl, unisex, newborn",
    )
    age_by_product: str | None = Field( 
        description="[SQL FILTER] Độ tuổi. GIÁ TRỊ HỢP LỆ: adult, kid, others",
    )
    master_color: str | None = Field(
        description=(
            "[SQL FILTER] Màu sắc sản phẩm. Gửi CHÍNH XÁC từ khách nói (VD: 'trắng', 'đen', 'xanh', 'đỏ'). "
            "Tool sẽ tự match trong DB bằng LIKE. KHÔNG đưa màu vào description!"
        ),
    )
    price_min: int | None = Field(
        description="[SQL FILTER] Giá thấp nhất (VND)",
    )
    price_max: int | None = Field(
        description="[SQL FILTER] Giá cao nhất (VND)",
    )
    discount_min: int | None = Field(
        description="[SQL FILTER] % giảm giá tối thiểu. VD: 50 → chỉ lấy SP giảm >= 50%. Nếu khách hỏi 'đồ sale' chung → đặt = 1.",
    )
    discount_max: int | None = Field(
        description="[SQL FILTER] % giảm giá tối đa. VD: 70 → chỉ lấy SP giảm <= 70%.",
    )
    product_line_vn: str | None = Field(
        description=(
            "[SQL FILTER] Đại loại sản phẩm — lọc RỘNG bằng prefix. "
            "Hỗ trợ nhiều giá trị cách bằng '/'. "
            "GIÁ TRỊ: 'Áo' (mọi loại áo), 'Quần' (mọi loại quần), "
            "'Váy' (váy liền + chân váy), 'Bộ' (bộ quần áo, bộ mặc nhà), "
            "'Khăn', 'Mũ', 'Túi', 'Tất', 'Chăn'. "
            "VD: 'áo khaki' → product_line_vn: 'Áo'. 'quần hoặc váy' → 'Quần/ Váy'"
        ),
    )
    discovery_mode: str | None = Field(
        description=(
            "[SQL FILTER] Chế độ khám phá. 'new' = hàng mới (is_new_product=1), "
            "'best_seller' = bán chạy nhất (ORDER BY quantity_sold). "
            "Chỉ dùng khi khách NÓI RÕ 'mới nhất'/'hàng mới'/'bán chạy'/'best seller'/'hot'. "
            "Nếu khách KHÔNG nói → để null."
        ),
    )


class MultiSearchParams(BaseModel):
    model_config = {"extra": "forbid"}  # STRICT MODE
    searches: list[SearchItem] = Field(description="Danh sách các truy vấn tìm kiếm")


@observe(name="db-query-search")
async def _execute_single_search(
    db, item: SearchItem, query_vector: list[float] | None = None
) -> tuple[list[dict], dict]:
    """
    Thực thi một search query đơn lẻ (Async).

    Returns:
        Tuple of (products, filter_info)
    """
    try:
        short_query = (
            (item.description[:60] + "...") if item.description and len(item.description) > 60 else item.description
        )
        logger.debug(
            "_execute_single_search started, query=%r, code=%r",
            short_query,
            item.magento_ref_code,
        )

        # Timer: build query (sử dụng vector đã có hoặc build mới)
        query_build_start = time.time()
        sql, params = await build_starrocks_query(item, query_vector=query_vector)
        query_build_time = (time.time() - query_build_start) * 1000  # Convert to ms
        logger.debug("SQL built, length=%s, build_time_ms=%.2f", len(sql), query_build_time)

        if not sql:
            return []

        # Timer: execute DB query
        db_start = time.time()
        products = await db.execute_query_async(sql, params=params)
        db_time = (time.time() - db_start) * 1000  # Convert to ms
        logger.info(
            "_execute_single_search done, products=%s, build_ms=%.2f, db_ms=%.2f, total_ms=%.2f",
            len(products),
            query_build_time,
            db_time,
            query_build_time + db_time,
        )

        # Debug: Log first product to see fields
        if products:
            first_p = products[0]
            logger.info("🔍 [DEBUG] First product keys: %s", list(first_p.keys()))
            logger.info(
                "🔍 [DEBUG] First product price: %s, sale_price: %s",
                first_p.get("original_price"),
                first_p.get("sale_price"),
            )
            logger.info(
                "🔍 [DEBUG] size_scale: %r, description_text: %r",
                first_p.get("size_scale"),
                (first_p.get("description_text") or "")[:100],
            )

        from langfuse import get_client as get_langfuse
        try:
            lf = get_langfuse()
            lf.update_current_observation(
                input={
                    "description": item.description[:200] if item.description else None,
                    "product_name": item.product_name,
                    "gender": item.gender_by_product,
                    "age": item.age_by_product,
                    "product_line_vn": item.product_line_vn,
                    "magento_ref_code": item.magento_ref_code,
                },
                output={
                    "raw_count": len(products),
                    "build_ms": round(query_build_time, 2),
                    "db_ms": round(db_time, 2),
                },
            )
        except Exception:
            pass  # Don't break if Langfuse not available

        return format_product_results(products), {"fallback_used": False}
    except Exception as e:
        logger.exception("Single search error for item %r: %s", item, e)
        return [], {"fallback_used": False, "error": str(e)}


@tool(args_schema=MultiSearchParams)
async def data_retrieval_tool(searches: list[SearchItem]) -> str:
    """
    Công cụ tìm kiếm sản phẩm CANIFA.
    Hỗ trợ tìm kiếm Semantic và lọc theo Metadata.
    """
    logger.info("🔧 data_retrieval_tool called with %d items", len(searches))

    # Get DB Connection
    db = get_db_connection()
    if not db:
        return json.dumps({"status": "error", "message": "Database connection failed"})

    combined_results = []
    all_filter_infos = []

    tasks = []
    for item in searches:
        tasks.append(_execute_single_search(db, item))

    results_list = await asyncio.gather(*tasks)

    for products, filter_info in results_list:
        combined_results.extend(products)
        if filter_info:
            all_filter_infos.append(filter_info)



    # Aggregate filter info from first result for simplicity in response
    final_info = all_filter_infos[0] if all_filter_infos else {}

    # Include search input so LLM knows its own reasoning
    search_inputs = [
        {
            "description": item.description,
            "product_line_vn": item.product_line_vn,
            "gender_by_product": item.gender_by_product,
            "age_by_product": item.age_by_product,
            "discovery_mode": item.discovery_mode,
        }
        for item in searches
    ]

    output = {
        "status": "success",
        "search_input": search_inputs,
        "results": combined_results,
        "filter_info": final_info,
    }

    logger.info(
        "🎁 Final result: %d products. Fallback used: %s",
        len(combined_results),
        final_info.get("fallback_used", False),
    )

    return json.dumps(output, ensure_ascii=False, default=str)


# Load dynamic docstring
# Load dynamic docstring
dynamic_prompt = read_tool_prompt("data_retrieval_tool")
if dynamic_prompt:
    data_retrieval_tool.__doc__ = dynamic_prompt
    data_retrieval_tool.description = dynamic_prompt
