#!/usr/bin/env python3
import os
import sys
import io
from typing import List, Dict, Any, Optional, Tuple
import multiprocessing

import logging
from pathlib import Path
import time
from curses.panel import top_panel
from email import message

from cv2 import log

from pydantic import BaseModel

from fastapi import FastAPI, HTTPException, APIRouter, Depends
from fastapi.responses import JSONResponse
from fastapi.middleware.cors import CORSMiddleware

from fastapi_utils.cbv import cbv
from fastapi_utils.inferring_router import InferringRouter

from sympy import content
import uvicorn

# 获取当前脚本的路径（Path 对象）
current_script = Path(__file__).resolve()
# 向上两级找到项目根目录（根据实际结构调整层级）
project_root = current_script.parents[1]  # parents[0] 是当前目录，parents[1] 是父目录，以此类推

print("project_root: ",project_root)

#添加到搜索路径
sys.path.append(str(project_root))

#查看系统环境
print("sys path:",sys.path)

from tools.core.common_functions import read_json_file
from models_server import Models_Server, TextInferenceRequest, MultimodalInferenceRequest, InferenceRequest
from models_server import _process_instance,_process_initialized

# 配置日志记录器
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)

shared_state = multiprocessing.Manager().dict()
shared_state["model_loaded"] = False
shared_state["model_path"] = ""
shared_state["load_start_time"] = 0
shared_state["load_complete"] = False

# # 请求模型
# class TextInferenceRequest(BaseModel):
#     user_prompt: str
#     max_tokens: int = 200
#     temperature: float = 0.7
#     top_p: float = 0.95
#     system_prompt: Optional[str] = None
#     stop: Optional[List[str]] = None

# class MultimodalInferenceRequest(BaseModel):
#     user_prompt: str
#     image_data: List[str]  # base64编码的图像数据列表
#     max_tokens: int = 300
#     temperature: float = 0.7
#     top_p: float = 0.95
#     system_prompt: Optional[str] = None
#     stop: Optional[List[str]] = None

# class InferenceRequest(BaseModel):
#     user_prompt: str
#     image_data: Optional[List[str]]=None  # base64编码的图像数据列表
#     max_tokens: int = 300
#     temperature: float = 0.7
#     top_p: float = 0.95
#     system_prompt: Optional[str] = None
#     stop: Optional[List[str]] = None

# 响应模型定义
class InferenceResponse(BaseModel):
    result: str
    metadata: Dict[str, Any]

class HealthResponse(BaseModel):
    status: str
    model_loaded: bool
    process_id: int
    load_time: float
    model_path: str

model_router = InferringRouter()  # 支持自动推断参数类型

# 依赖注入：获取单例模型服务
def get_model_server() -> Models_Server:
    """依赖注入：获取当前进程的单例服务实例"""
    logger.info(f"=== get_model_server 被触发！Process ID: {os.getpid()} ===")

    if _process_instance is None:
        config_json_file = f"{project_root}/config/model_config.json"  # ✅ 修正路径
        print("config_json_file: ", config_json_file)
        
        # 读取配置文件
        config_data = read_json_file(config_json_file)
        if config_data is None:
            logger.error(f"get_model_server: 无法读取配置文件 '{config_json_file}'")
            raise HTTPException(status_code=500, detail=f"无法读取配置文件: {config_json_file}")
        
        # 检查 models_server 配置是否存在
        if "models_server" not in config_data:
            logger.error("get_model_server: 配置文件中缺少 'models_server' 字段")
            raise HTTPException(status_code=500, detail="配置文件中缺少 'models_server' 字段")
        
        # 如果 models_server 是列表，取第一个；如果是字典，直接使用
        models_server_data = config_data["models_server"]
        model_server_config = models_server_data[0] if isinstance(models_server_data, list) else models_server_data

        if model_server_config is None:
            logger.error("get_model_server: 配置未初始化！")
            raise HTTPException(status_code=500, detail="服务配置未初始化")
        
        # 获取单例实例
        model_server = Models_Server(model_server_config)
        if not model_server.model_loaded:
            model_server._wait_for_model_load(model_server_config)
            model_server.init_model(model_server_config["model_inference_framework_type"],
                                    model_server_config)
    else:
        model_server = _process_instance
        if not model_server.model_loaded:
            # 重新读取配置以获取 model_server_config
            config_json_file = f"{project_root}/config/model_config.json"
            config_data = read_json_file(config_json_file)
            if config_data is None or "models_server" not in config_data:
                logger.error("get_model_server: 无法读取配置文件")
                raise HTTPException(status_code=500, detail="无法读取配置文件")
            models_server_data = config_data["models_server"]
            model_server_config = models_server_data[0] if isinstance(models_server_data, list) else models_server_data
            model_server._wait_for_model_load(model_server_config)
            model_server.init_model(model_server_config["model_inference_framework_type"],
                                    model_server_config)

    logger.info(f"get_model_server 返回实例状态: 加载={model_server.model_loaded}, Process ID={model_server.process_id}")
    return model_server

@cbv(model_router)  # 将类与路由绑定
class Models_Controller:

    def __init__(self, model_server: Models_Server = Depends(get_model_server)):
        self.model_server = model_server  # 实例变量，确保每个请求可用
        logger.info(f"Models_Controller init success! Process ID: {os.getpid()}")

        """
        初始化成员变量
        """
        #model: vlm，llm
        # model_server = Depends(get_model_server)  
        # self.model_loaded = False
        # self.load_start_time = 0.0
        # self.inference_start_time = 0.0

        # #定义服务器地址和端口
        # self.model_server_host = None
        # self.model_server_port = None
        # logger.info("Models_Controller init success!")
        
        # def parse_config(self,config_path):

    def set_model_server_host(self,model_server_host):
        """
        设置模型推理服务器的地址
        """
        try:
            self.model_server_host = model_server_host
            return True
        except Exception as e:
            logger.error(f"设置模型推理服务器的地址失败: {str(e)}")
            return False
    
    def set_model_server_port(self,model_server_port):
        """
        设置模型推理服务器的端口
        """
        try:
            self.model_server_port = model_server_port
            return True
        except Exception as e:
            logger.error(f"设置模型推理服务器的端口失败: {str(object=e)}")
            return False

    @model_router.post("/text/inference", response_model=Dict[str, Any])
    async def text_inference(self, request: TextInferenceRequest):
        """纯文本推理端点"""

        return self.model_server.text_inference(request=request)

    @model_router.post("/multimodal/inference", response_model=Dict[str, Any])
    async def multimodal_inference(self,request: MultimodalInferenceRequest):
        """大模型多模态推理（文本+图像）端点"""
        
        return self.model_server.multimodal_inference(request=request)
    
    @model_router.post("/model/inference", response_model=Dict[str, Any])
    async def model_inference(self,request: InferenceRequest):
        """大模型(纯文本或多模态（文本+图像））推理端点"""
        
        return self.model_server.model_inference(request=request)

    # API端点
    @model_router.get("/model/health", response_model=Dict[str, Any])
    async def model_health_check(self):
        """检查大模型服务健康状态"""

        return {
            "status": "healthy" if shared_state["model_loaded"] else "loading",
            "model_loaded": shared_state["model_loaded"],
            "process_id": self.model_server.process_id,
            "load_time": shared_state.get("load_time", 0),
            "model_path": shared_state.get("model_path", "")
        }

  
# def start_http_model_controller( model_server_host="localhost",model_server_port=8000,model_workers=1):
#     """
#     初始化并启用FastAPI应用
#     """
#     # #初始化加载模型
#     # self.init_model(config["model_inference_framework_type"],config)
#     # 初始化FastAPI应用
#     model_app = FastAPI(title="多模态大模型推理服务") 
#     # 配置CORS
#     # model_app.add_middleware(
#     #     CORSMiddleware,
#     #     allow_origins=["*"],
#     #     allow_credentials=True,
#     #     allow_methods=["*"],
#     #     allow_headers=["*"],
#     # )
#     try:
#         # 将路由注册到 app
#         model_app.include_router(model_router)

#         
#         uvicorn.run(app=model_app, host=model_server_host, port=model_server_port,workers=model_workers)
#         return True
#     except Exception as e:
#         logger.error(f"初始化并启用FastAPI应用失败: {str(e)}")
#         return False

def create_app() -> FastAPI:
    """创建FastAPI应用"""
    app = FastAPI(title="Multimodal API", version="1.0")
    
    # 配置CORS
    # app.add_middleware(
    #     CORSMiddleware,
    #     allow_origins=["*"],
    #     allow_credentials=True,
    #     allow_methods=["*"],
    #     allow_headers=["*"],
    # )
    
    # 注册路由
    app.include_router(model_router)
    
    return app


def main():
    #model server 和client初始化
    # models_server = Models_Server()

    # from tools.core.common_functions import read_json_file
    # "/home/ubuntu/Workspace/Projects/VLM_VLA/UAV_AI/src/Model/AI_Agent/scripts/ai_agent/models/model_config.json"
    print(f"project_root111:{project_root}")
    config_json_file= f"{project_root}/models/model_config.json"
    print("config_json_file: ",config_json_file)
    # global model_server_config
    model_server_config = read_json_file(config_json_file)["models_server"]

    # while( not models_server.model_loaded ) :
    #     models_server.init_model(model_inference_framework_type=model_server_config["model_infer恩策_framework_type"],
    #                          config=model_server_config)
    # logger.info("model_loaded success!")
    # start_http_model_controller(model_server_host=model_server_config["model_server_host"],
    #                             model_server_port=model_server_config["model_server_port"])
    # model_server_config= {
    #         "model_inference_framework_type":"llama_cpp",
    #         "multi_modal":1,
    #         "chat_handler": "Qwen25VLChatHandler",
    #         "vlm_model_path":"/home/ubuntu/Workspace/Projects/VLM_VLA/Models/Qwen2.5-VL-3B-Instruct-GGUF/Qwen2.5-VL-3B-Instruct-Q8_0.gguf",
    #         "mmproj_model_path":"/home/ubuntu/Workspace/Projects/VLM_VLA/Models/Qwen2.5-VL-3B-Instruct-GGUF/mmproj-model-f16.gguf",
    #         "n_ctx":30720,
    #         "n_threads":4,
    #         "n_gpu_layers":40,
    #         "n_batch":24,
    #         "verbose":1,
    #         "model_server_host":"localhost",
    #         "model_server_port":8000,
    #         "model_controller_workers":1
    #     }
    # print("model_server_config: ",model_server_config)
    uvicorn.run(
        app="models_controller:create_app",
        host=model_server_config["model_server_host"],
        port=model_server_config["model_server_port"],
        workers=model_server_config["model_controller_workers"],
        factory=True,
        log_level="info"
    )


if __name__ == "__main__":
    main()
    # test_inference(0)
    logger.info("work finish")

