"""
项目配置文件
从.env文件读取配置
"""
import os
from dotenv import load_dotenv
from contextvars import ContextVar
from typing import Optional, Dict, Any

# 加载.env文件
load_dotenv()

# ==================== 大模型配置 ====================
LLM_CONFIG = {
#    "model": "Qwen3.5-35B-A3B",
    "model": "46-qwen3.5-35B",
#    "model": "Qwen3-14B",
    "base_url": "http://192.168.0.46:59800/v1",
    "api_key": "gpustack_dee9ca823290886c_5edfc86aeeeceb1e9ee5162941cb2cb5",
    "temperature": float("0.1"),
    "max_tokens": int("8192"),
    "timeout": int("30")
}

# ==================== 嵌入模型配置 ====================
EMBEDDING_CONFIG = {
    "model": "bge-m3",
    "base_url": "http://192.168.0.46:59700/v1/embeddings",
    "api_key": "gpustack_dee9ca823290886c_5edfc86aeeeceb1e9ee5162941cb2cb5",
    "base_url_v2" : "http://192.168.0.46:59700/v1",
}


# ==================== 线程安全的请求上下文配置 ====================
# 使用 contextvars 存储每个请求的用户配置，确保多用户并发时不会相互干扰
_request_user_config: ContextVar[Optional[Dict[str, str]]] = ContextVar('request_user_config', default=None)

# RAG配置的默认值
_RAG_CONFIG_DEFAULT = {
    "search_endpoint": "http://192.168.0.46:11000/api/v1/knowledge/search/",
    "x-user-id": "1",
    "x-user-name": "testuser",
    "x-role": "admin",
    "kb-id": None,
    "file-id": None
}

class DynamicRAGConfig(dict):
    """
    动态RAG配置类，支持线程安全的请求级配置
    当访问用户相关配置时，自动从当前请求上下文读取
    其他配置项直接返回默认值
    兼容字典的所有操作方式（如 get(), [], in 等）
    """
    def __getitem__(self, key: str):
        # 如果是用户相关配置或知识库参数，从当前请求上下文读取
        if key in ["x-user-id", "x-user-name", "x-role", "kb-id", "file-id"]:
            request_config = _request_user_config.get()
            if request_config and key in request_config:
                return request_config[key]
            # 如果没有设置，返回默认值
            return _RAG_CONFIG_DEFAULT[key]
        # 其他配置项直接返回默认值
        return _RAG_CONFIG_DEFAULT.get(key)
    
    def get(self, key: str, default=None):
        """支持 get() 方法"""
        try:
            return self[key]
        except KeyError:
            return default
    
    def __contains__(self, key: str):
        """支持 in 操作符"""
        return key in _RAG_CONFIG_DEFAULT
    
    def keys(self):
        """返回所有键"""
        return _RAG_CONFIG_DEFAULT.keys()
    
    def values(self):
        """返回所有值（动态读取用户配置）"""
        return [self[key] for key in _RAG_CONFIG_DEFAULT.keys()]
    
    def items(self):
        """返回所有键值对（动态读取用户配置）"""
        return [(key, self[key]) for key in _RAG_CONFIG_DEFAULT.keys()]

# ==================== RAG服务配置 ====================
# 使用动态配置类，支持多用户并发时自动读取各自的配置
RAG_CONFIG = DynamicRAGConfig()

def set_request_user_config(x_user_id: Optional[str] = None, 
                            x_user_name: Optional[str] = None, 
                            x_role: Optional[str] = None,
                            text_kb_id: Optional[str] = None,
                            text_file_id: Optional[str] = None):
    """
    设置当前请求的用户配置和知识库参数（线程安全）
    
    Args:
        x_user_id: 用户ID
        x_user_name: 用户名称
        x_role: 角色
        text_kb_id: 文本检索知识库ID
        text_file_id: 文本检索文件ID
    """
    config = {}
    if x_user_id is not None:
        config["x-user-id"] = x_user_id
    if x_user_name is not None:
        config["x-user-name"] = x_user_name
    if x_role is not None:
        config["x-role"] = x_role
    # 仅当非空字符串时才设置，空字符串时不传入 RAG 接口
    if text_kb_id is not None and str(text_kb_id).strip():
        config["kb-id"] = str(text_kb_id).strip()
    if text_file_id is not None and str(text_file_id).strip():
        config["file-id"] = str(text_file_id).strip()
    _request_user_config.set(config if config else None)

# ==================== 图谱检索服务配置 ====================
GRAPH_SEARCH_CONFIG = {
    "search_endpoint": "http://192.168.0.46:59085/search_graph",
    "graph_timeout": float("30.0"),
    "default_top_k": int("10"),
    "operation_search_endpoint": "http://192.168.0.46:59085/operation_graph_search"
}

# ==================== 设备到系统检索服务配置 ====================
DEVICE_SYSTEM_CONFIG = {
    "endpoint": "http://192.168.0.46:59085/device_to_system",
    "timeout": float("30.0"),
    "default_min_hops": int("2"),
    "default_max_hops": int("8"),
    "default_top_k": int("10")
}

# ==================== 图册检索服务配置 ====================
ATLAS_CONFIG = {
    "endpoint": "http://192.168.0.46:59085/atlas_retrieval",
    "timeout": float("30.0"),
    "default_top_k": int("10")
}

# ==================== 工作流配置 ====================
WORKFLOW_CONFIG = {
    "max_retry_count": int("2"),  # 最大重试次数
    "image_clarity_threshold": float("0.7"),  # 图片清晰度阈值
    "default_timeout": int("30")  # 默认超时时间（秒）
}

# ==================== 服务器配置 ====================
SERVER_CONFIG = {
    "host": "192.168.0.46",
    "port": "59088",
    "base_url": "http://192.168.0.46:59088"
}

# ==================== ASR服务配置 ====================
ASR_CONFIG = {
    "api_base": "http://192.168.0.46:59900/v1",
    "model": "base",
    "language": "zh",
    "timeout": int("30")
}

# ==================== VLM服务配置 ====================
VLM_CONFIG = {
    "api_base" : "http://192.168.0.46:59801/v1",
    "model" :  "Qwen3-VL-8B"
}

# ==================== Neo4J配置 ====================
NEO4J_CONFIG = {
    "uri": "neo4j://192.168.0.46:57687",
    "user": "neo4j",
    "password": "zdht123@"
}

# ==================== 知识库匹配配置 ====================
KB_TREE_CONFIG = {
    "url": "http://192.168.0.46:11000/api/v1/knowledge/knowledge_base/tree"
}

# ==================== 维修反馈统计配置 ====================
REPAIR_FEEDBACK_CONFIG = {
    "url": "http://192.168.0.46:22000",
    "email": "15088888888@163.com",
    "password": "11223344"
}

# ==================== 数据库配置 ====================
POSTGRES_CONNECTION_STRING = "postgresql://postgres:password@192.168.0.46:5432/an_webui"
#POSTGRES_CONNECTION_STRING = "postgresql+psycopg://postgres:password@192.168.0.46:5432/an_webui"
POSTGRES_SQLALCHEMY_URL = "postgresql+psycopg://postgres:password@192.168.0.46:5432/an_webui"


# ==================== 索引配置 ====================
INDEX_CONFIG = {
    "NAME_PROPERTY" : "名称",
    "FULLTEXT_PROPERTY" :"fulltext",
    "EMBEDDING_PROPERTY" : "embedding",
    "SEARCH_LABEL" : "Searchable",
    "VECTOR_INDEX_NAME" : "global_searchable_embedding",
    "FULLTEXT_INDEX_NAME" : "global_searchable_content_search"
}

# ==================== sql表格字段与neo4j节点映射 ====================
MAP_INS={
    "故障模式" : "fault",
    "系统" : "system_name",
    "设备" : "device_name",
    "舷号" : "ship_number",
}

# ==================== neo4j配置 ====================
NEO4J_CONFIG = {
    "uri": "neo4j://192.168.0.46:57687",
    "user": "neo4j",
    "password": "zdht123@"
}
API_URLS = [
      "http://192.168.0.46:59988/analyze-pdf",
    # "http://192.168.0.111:9977/analyze-pdf",
    # "http://192.168.0.111:9978/analyze-pdf",
    #"http://192.168.0.111:9979/analyze-pdf",
    #"http://192.168.0.111:9980/analyze-pdf",
    # "http://192.168.0.111:9975/analyze-pdf",
]
# ==================== 切片图片处理配置 ====================
MAX_SPLIT_IMAGE_INPUT_BYTES = 50 * 1024 * 1024
MAX_SPLIT_IMAGE_BYTES = 10 * 1024 * 1024
MAX_SPLIT_IMAGE_BASE64_CHARS = (MAX_SPLIT_IMAGE_INPUT_BYTES * 4 // 3) + 4096
SPLIT_IMAGE_COMPRESS_THRESHOLD_BYTES = MAX_SPLIT_IMAGE_BYTES
SPLIT_IMAGE_MAX_DIMENSION = 4096
SPLIT_IMAGE_JPEG_QUALITY = 88
OCR_CONCURRENCY = 1
VLM_CONCURRENCY = 2

SHIP_MODEL_NAME = "/app/ship_xinghao.json"
TREE_JSON_PATH = "/app/tree_data.json"
# ==================== mineru和kgrag目录映射地址 ====================
SEARCH_DIR ="/app/mineru_output"
IMAGE_DIR = "/app/mineru_output/images"