import os
import sys
import io
import time
import numpy as np
from fastapi import APIRouter, UploadFile, File, Form, HTTPException
from fastapi.responses import JSONResponse
from PIL import Image
from loguru import logger

# Đường dẫn đến module image_process
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
IMAGE_PROCESS_DIR = os.path.join(BASE_DIR, "image_process")
if IMAGE_PROCESS_DIR not in sys.path:
    sys.path.append(IMAGE_PROCESS_DIR)

from core.encoder import ImageEncoder
from common.starrocks_connection import StarRocksConnection

router = APIRouter(prefix="/api/recommend", tags=["Recommendation StarRocks"])

# Singleton
_encoder = None
_db = StarRocksConnection()

def get_encoder():
    global _encoder
    if _encoder is None:
        _encoder = ImageEncoder()
    return _encoder

@router.post("/image")
async def recommend_by_image(
    file: UploadFile = File(...),
):
    """
    API tìm kiếm sản phẩm bằng ảnh - Hardcoded StarRocks SQL logic
    """
    start_time = time.time()
    encoder = get_encoder()
    
    try:
        # 1. Xử lý ảnh và lấy Vector
        contents = await file.read()
        img = Image.open(io.BytesIO(contents)).convert("RGB")
        
        # Trích xuất vector 768-dim
        vector = encoder.encode_image(img)
        # Chuyển vector sang định dạng string [v1, v2, ...] để gắn vào SQL
        v_str = "[" + ",".join(map(str, vector.tolist())) + "]"
        
        # 2. Optimized SQL cho StarRocks (sử dụng HNSW Vector Index)
        # Bảng đích: magento_product_dimension_with_image_embedding
        target_table = "shared_source.magento_product_dimension_with_image_embedding"
        ef_search = 128  # HNSW ef_search parameter (higher = more accurate, slower)
        
        sql = f"""
        WITH top_sku_candidates AS (
            SELECT
                /*+ SET_VAR(ann_params='{{"ef_search":{ef_search}}}') */
                internal_ref_code,
                product_name,
                sale_price,
                original_price,
                master_color,
                product_image_url,
                product_image_url_thumbnail,
                product_web_url,
                description_text,
                material,
                material_group,
                gender_by_product,
                age_by_product,
                season,
                style,
                fitting,
                form_neckline,
                form_sleeve,
                product_line_vn,
                product_color_name,
                approx_cosine_similarity(vector, {v_str}) as similarity_score
            FROM {target_table}
            ORDER BY similarity_score DESC
            LIMIT 50
        )
        SELECT
            internal_ref_code,
            MAX_BY(product_name, similarity_score) as product_name,
            MAX_BY(sale_price, similarity_score) as sale_price,
            MAX_BY(original_price, similarity_score) as original_price,
            GROUP_CONCAT(DISTINCT master_color ORDER BY master_color SEPARATOR ', ') as available_colors,
            MAX_BY(product_image_url, similarity_score) as product_image_url,
            MAX_BY(product_image_url_thumbnail, similarity_score) as product_image_url_thumbnail,
            MAX_BY(product_web_url, similarity_score) as product_web_url,
            MAX_BY(description_text, similarity_score) as description_text,
            MAX_BY(material, similarity_score) as material,
            MAX_BY(material_group, similarity_score) as material_group,
            MAX_BY(gender_by_product, similarity_score) as gender_by_product,
            MAX_BY(age_by_product, similarity_score) as age_by_product,
            MAX_BY(season, similarity_score) as season,
            MAX_BY(style, similarity_score) as style,
            MAX_BY(fitting, similarity_score) as fitting,
            MAX_BY(form_neckline, similarity_score) as form_neckline,
            MAX_BY(form_sleeve, similarity_score) as form_sleeve,
            MAX_BY(product_line_vn, similarity_score) as product_line_vn,
            MAX(similarity_score) as similarity_score
        FROM top_sku_candidates
        GROUP BY internal_ref_code
        ORDER BY similarity_score DESC
        LIMIT 10
        """
        
        # 3. Thực thi query
        results = await _db.execute_query_async(sql)
        
        process_time = time.time() - start_time
        logger.info(f"Visual search done in {process_time:.3f}s. Found {len(results)} groups.")
        
        return {
            "status": "success",
            "process_time": f"{process_time:.3f}s",
            "results": results
        }
        
    except Exception as e:
        logger.error(f"Recommend Error: {e}")
        return JSONResponse(
            status_code=500,
            content={"status": "error", "message": str(e)}
        )
