import asyncio
import json
import logging
import time

from fastapi import APIRouter, BackgroundTasks, HTTPException
from pydantic import BaseModel

from agent.tools.data_retrieval_tool import SearchItem, data_retrieval_tool
from agent.mock_controller import mock_chat_controller

logger = logging.getLogger(__name__)
router = APIRouter()


# --- HELPERS ---
async def retry_with_backoff(coro_fn, max_retries=3, backoff_factor=2):
    """Retry async function with exponential backoff"""
    for attempt in range(max_retries):
        try:
            return await coro_fn()
        except Exception as e:
            if attempt == max_retries - 1:
                raise
            wait_time = backoff_factor**attempt
            logger.warning(f"⚠️ Attempt {attempt + 1} failed: {e!s}, retrying in {wait_time}s...")
            await asyncio.sleep(wait_time)


# --- MODELS ---
class MockQueryRequest(BaseModel):
    user_query: str
    user_id: str | None = "test_user"
    session_id: str | None = None
    images: list[str] | None = None


class MockDBRequest(BaseModel):
    query: str | None = None
    magento_ref_code: str | None = None
    price_min: float | None = None
    price_max: float | None = None
    top_k: int = 10


class MockRetrieverRequest(BaseModel):
    user_query: str
    price_min: float | None = None
    price_max: float | None = None
    magento_ref_code: str | None = None
    user_id: str | None = "test_user"
    session_id: str | None = None


# --- MOCK LLM RESPONSES (không gọi OpenAI) ---
MOCK_AI_RESPONSES = [
    "Dựa trên tìm kiếm của bạn, tôi tìm thấy các sản phẩm phù hợp với nhu cầu của bạn. Những mặt hàng này có chất lượng tốt và giá cả phải chăng.",
    "Tôi gợi ý cho bạn những sản phẩm sau. Chúng đều là những lựa chọn phổ biến và nhận được đánh giá cao từ khách hàng.",
    "Dựa trên tiêu chí tìm kiếm của bạn, đây là những sản phẩm tốt nhất mà tôi có thể giới thiệu.",
    "Những sản phẩm này hoàn toàn phù hợp với yêu cầu của bạn. Hãy xem chi tiết để chọn sản phẩm yêu thích nhất.",
    "Tôi đã tìm được các mặt hàng tuyệt vời cho bạn. Hãy kiểm tra chúng để tìm ra lựa chọn tốt nhất.",
]


# --- ENDPOINTS ---

@router.post("/api/mock/agent/chat", summary="Mock Agent Chat (Real Tools + Fake LLM)")
async def mock_chat(req: MockQueryRequest, background_tasks: BackgroundTasks):
    """
    Mock Agent Chat using mock_chat_controller:
    - ✅ Real embedding + vector search (data_retrieval_tool THẬT)
    - ✅ Real products from StarRocks
    - ❌ Fake LLM response (no OpenAI cost)
    - Perfect for stress testing + end-to-end testing
    """
    try:
        logger.info(f"🚀 [Mock Agent Chat] Starting with query: {req.user_query}")

        result = await mock_chat_controller(
            query=req.user_query,
            user_id=req.user_id or "test_user",
            background_tasks=background_tasks,
            images=req.images,
        )

        return {
            "status": "success",
            "user_query": req.user_query,
            "user_id": req.user_id,
            "session_id": req.session_id,
            **result,  # Include status, ai_response, product_ids, etc.
        }

    except Exception as e:
        logger.error(f"❌ Error in mock agent chat: {e!s}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Mock Agent Chat Error: {e!s}")


@router.post("/api/mock/db/search", summary="Real Data Retrieval Tool (Agent Tool)")
async def mock_db_search(req: MockDBRequest):
    """
    Dùng `data_retrieval_tool` THẬT từ Agent:
    - Nếu có magento_ref_code → CODE SEARCH (không cần embedding)
    - Nếu có query → HYDE SEMANTIC SEARCH (embedding + vector search)
    - Lọc theo giá nếu có price_min/price_max
    - Trả về sản phẩm thực từ StarRocks

    Format input giống SearchItem của agent tool.
    """
    try:
        logger.info("📍 Data Retrieval Tool called")
        start_time = time.time()

        # Xây dựng SearchItem từ request - include all required fields
        search_item = SearchItem(
            query=req.query or "sản phẩm",
            magento_ref_code=req.magento_ref_code,
            price_min=req.price_min,
            price_max=req.price_max,
            action="search",
            # Metadata fields - all required with None default
            gender_by_product=None,
            age_by_product=None,
            product_name=None,
            style=None,
            master_color=None,
            season=None,
            material_group=None,
            fitting=None,
            form_neckline=None,
            form_sleeve=None,
        )


        logger.info(f"🔧 Search params: {search_item.dict(exclude_none=True)}")

        # Gọi data_retrieval_tool THẬT với retry
        result_json = await retry_with_backoff(
            lambda: data_retrieval_tool.ainvoke({"searches": [search_item]}), max_retries=3
        )
        result = json.loads(result_json)

        elapsed_time = time.time() - start_time
        logger.info(f"✅ Data Retrieval completed in {elapsed_time:.3f}s")

        return {
            "status": result.get("status", "success"),
            "search_params": search_item.dict(exclude_none=True),
            "total_results": len(result.get("results", [{}])[0].get("products", [])),
            "products": result.get("results", [{}])[0].get("products", []),
            "processing_time_ms": round(elapsed_time * 1000, 2),
            "raw_result": result,
        }

    except Exception as e:
        logger.error(f"❌ Error in DB search: {e!s}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"DB Search Error: {e!s}")


@router.post("/api/mock/retrieverdb", summary="Real Embedding + Real DB Vector Search")
@router.post("/api/mock/retriverdb", summary="Real Embedding + Real DB Vector Search (Legacy)")
async def mock_retriever_db(req: MockRetrieverRequest):
    """
    API thực tế để test Retriever + DB Search (dùng agent tool):
    - Lấy query từ user
    - Embedding THẬT (gọi OpenAI embedding trong tool)
    - Vector search THẬT trong StarRocks
    - Trả về kết quả sản phẩm thực (bỏ qua LLM)

    Dùng để test performance của embedding + vector search riêng biệt.
    """
    try:
        logger.info(f"📍 Retriever DB started: {req.user_query}")
        start_time = time.time()

        # Xây dựng SearchItem từ request - include all required fields
        search_item = SearchItem(
            query=req.user_query,
            magento_ref_code=req.magento_ref_code,
            price_min=req.price_min,
            price_max=req.price_max,
            action="search",
            # Metadata fields - all required with None default
            gender_by_product=None,
            age_by_product=None,
            product_name=None,
            style=None,
            master_color=None,
            season=None,
            material_group=None,
            fitting=None,
            form_neckline=None,
            form_sleeve=None,
        )


        logger.info(f"🔧 Retriever params: {search_item.dict(exclude_none=True)}")

        # Gọi data_retrieval_tool THẬT (embedding + vector search) với retry
        result_json = await retry_with_backoff(
            lambda: data_retrieval_tool.ainvoke({"searches": [search_item]}), max_retries=3
        )
        result = json.loads(result_json)

        elapsed_time = time.time() - start_time
        logger.info(f"✅ Retriever completed in {elapsed_time:.3f}s")

        # Parse kết quả
        search_results = result.get("results", [{}])[0]
        products = search_results.get("products", [])

        return {
            "status": result.get("status", "success"),
            "user_query": req.user_query,
            "user_id": req.user_id,
            "session_id": req.session_id,
            "search_params": search_item.dict(exclude_none=True),
            "total_results": len(products),
            "products": products,
            "processing_time_ms": round(elapsed_time * 1000, 2),
        }

    except Exception as e:
        logger.error(f"❌ Error in retriever DB: {e!s}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Retriever DB Error: {e!s}")
