import json
import mysql.connector
from mysql.connector import Error
from typing import Any, Dict, List, Sequence
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent
from mcp.shared.exceptions import McpError
from datetime import datetime,date
import re
import decimal
import os
from dotenv import load_dotenv
# version = "0.8.15"
load_dotenv()

MYSQL_CONFIG = {
    'host': os.getenv('DB_HOST'),
    'port': int(os.getenv('DB_PORT', 3306)),  # 默认 3306
    'user': os.getenv('DB_USER'),
    'password': os.getenv('DB_PASSWORD'),
    'database': os.getenv('DB_NAME'),
    'charset': os.getenv('DB_CHARSET', 'utf8mb4'),
    'ssl_disabled': True,
}

def _make_json_serializable(obj):
    if isinstance(obj, (datetime, date)):
        return obj.isoformat()  # 如 "2024-06-01T00:00:00"
    elif isinstance(obj, decimal.Decimal):
        return float(obj)  # 或 str(obj) 如果要保留精度
    elif isinstance(obj, dict):
        return {k: _make_json_serializable(v) for k, v in obj.items()}
    elif isinstance(obj, list):
        return [_make_json_serializable(item) for item in obj]
    else:
        return obj
def agro_product_search_recommend(product_chunks: List[Dict[str, Any]], user_preferences: Dict[str, str] = None) -> Dict[str, Any]:
    connection = None
    try:
        connection = mysql.connector.connect(**MYSQL_CONFIG)
        cursor = connection.cursor(dictionary=True)

        all_skus=[]
        for chunk in product_chunks:
            prod_id = chunk.get("prod_id")
            registration_no= chunk.get("registration_no")
            name = chunk.get("name")
            skus = []

            cursor.execute("""
                SELECT prod_id, name, content,views,buys,comments,brand_id
                    FROM ls_prod 
                    WHERE prod_id = %s AND status = 1
            """, (prod_id,))
            prod_info=cursor.fetchall()
            if len(prod_info)!=1:
                continue
    
            # SELECT * FROM ls_sku WHERE prod_id = %s AND status = 1
            cursor.execute("""
                SELECT sku_id, prod_id,name, cn_properties, price, stocks, prod_date, pic, overdue_month,small_quantity,small_unit,large_quantity,large_unit
                    FROM ls_sku 
                    WHERE prod_id = %s AND status = 1
            """, (prod_id,))
            skus_info = cursor.fetchall()
    
            for sku in skus_info:
                sku_info={
                    "sku_id": sku.get("sku_id"),
                    "prod_id": sku.get("prod_id"),
                    "price": sku.get("price"),
                    "stocks": sku.get("stocks"),
                    "prod_date": sku.get("prod_date"),
                    "pic": sku.get("pic"),
                    "overdue_month": sku.get("overdue_month"),
                    "small_quantity": sku.get("small_quantity"),
                    "small_unit": sku.get("small_unit"),
                    "large_quantity": sku.get("large_quantity"),
                    "large_unit": sku.get("large_unit"),
                    'comments': prod_info[0].get("comments"),
                    'views': prod_info[0].get("views"),
                    'buys': prod_info[0].get("buys"),
                    'name': sku.get("name"),
                }
                all_skus.append(sku_info)
 
        if user_preferences:
            if user_preferences.get("price_preference") == "cheapest":
                all_skus.sort(key=lambda x: (x["price"] is None, x["price"]))
            elif user_preferences.get("date_preference") == "recent":
                # 生产日期降序（越新越靠前）
                # ISO 8601 字符串可直接比较，但需处理 None
                all_skus.sort(key=lambda x: (x["prod_date"] is None, x["prod_date"]), reverse=True)
            elif user_preferences.get("popularity_preference") == "best_selling":
                # 按 buys 降序（销量越高越靠前），buys 为 None 时排最后
                all_skus.sort(key=lambda x: (x["buys"] is not None, x["buys"]), reverse=True)


        for item in all_skus:
            if item["pic"]:
                item["pic"] = f'https://kingnew-niu68.oss-cn-shanghai.aliyuncs.com/{item["pic"]}'
        results = _make_json_serializable(all_skus)
        return {"message": "Success", "data": results}

    except Exception as e:
        print(f'Error: {str(e)}')
        return {"message": "Error", "error": str(e)}
    finally:
        if connection and connection.is_connected():
            cursor.close()
            connection.close()




# ========== MCP Server ==========
async def serve() -> None:  
    server = Server("nbotbb-agro-mcp")
    @server.list_tools()
    async def list_tools() -> list[Tool]:
        return [
            Tool(
                name="agro_product_search_recommend",
                description="根据从知识库检索到的切片，结构化商品的输入信息，从而从数据库中查询商品更详细信息，然后根据用户偏好进行推荐。",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "product_chunks": {
                            "type": "array",
                            "description": "根据从知识库检索到的切片，结构化商品的输入信息，从而从数据库中查询商品更详细信息。",
                            "items": {
                                "type": "object",
                                "properties": {
                                    "prod_id": {"type": "string", "description": "商品ID"},
                                    "registration_no": {"type": "string", "description": "商品注册号"},
                                    "name": {"type": "string", "description": "商品名称"},
                                },
                                "required": ["prod_id", "name"],
                                "additionalProperties": False
                            }
                        },
                        "user_preferences": {
                            "type": "object",
                            "description": "用户偏好设置（仅当用户明确表达时提供）",
                            "properties": {
                                "price_preference": {
                                    "type": "string",
                                    "enum": ["cheapest"]
                                },
                                "date_preference": {
                                    "type": "string",
                                    "enum": ["recent"]
                                },
                                "popularity_preference": {
                                    "type": "string",
                                    "enum": ["best_selling"]
                                }
                            },
                            "required": [],
                            "additionalProperties": False
                        }
                    },
                    "required": ["product_chunks"],
                    "additionalProperties": False
                }
            )
    ]
            
            
    @server.call_tool()
    async def call_tool(name: str, arguments: dict) -> Sequence[TextContent]:
        try:
            if name == "agro_product_search_recommend":
                res = agro_product_search_recommend(
                    product_chunks=arguments["product_chunks"],
                    user_preferences=arguments.get("user_preferences")
                )
            else:
                raise ValueError(f"Unknown tool: {name}")

            return [TextContent(type="text", text=json.dumps(res, ensure_ascii=False))]

        except Exception as e:
            return [TextContent(type="text", text=json.dumps({"message": "Error", "error": str(e)}, ensure_ascii=False))]
            

    options = server.create_initialization_options()
    async with stdio_server() as (read_stream, write_stream):
        await server.run(read_stream, write_stream, options)