import os
import secrets
from typing import List, Optional

from pydantic_settings import BaseSettings


class Settings(BaseSettings):
    PROJECT_NAME: str = "RAG Web UI"  # Project name
    VERSION: str = "0.1.0"  # Project version
    API_V1_STR: str = "/api"  # API version string
    ENVIRONMENT: str = os.getenv("ENVIRONMENT", os.getenv("APP_ENV", "development"))

    # MySQL settings
    MYSQL_SERVER: str = os.getenv("MYSQL_SERVER", "localhost")
    MYSQL_PORT: int = int(os.getenv("MYSQL_PORT", "3306"))
    MYSQL_USER: str = os.getenv("MYSQL_USER", "ragagent")
    MYSQL_PASSWORD: str = os.getenv("MYSQL_PASSWORD", "ragagent")
    MYSQL_DATABASE: str = os.getenv("MYSQL_DATABASE", "ragagent")
    SQLALCHEMY_DATABASE_URI: Optional[str] = None

    @property
    def get_database_url(self) -> str:
        if self.SQLALCHEMY_DATABASE_URI:
            return self.SQLALCHEMY_DATABASE_URI
        return (
            f"mysql+mysqlconnector://{self.MYSQL_USER}:{self.MYSQL_PASSWORD}"
            f"@{self.MYSQL_SERVER}:{self.MYSQL_PORT}/{self.MYSQL_DATABASE}"
        )

    # JWT settings
    SECRET_KEY: str = os.getenv("SECRET_KEY", "")
    ALGORITHM: str = "HS256"
    ACCESS_TOKEN_EXPIRE_MINUTES: int = int(os.getenv("ACCESS_TOKEN_EXPIRE_MINUTES", "10080"))

    # Chat Provider settings
    CHAT_PROVIDER: str = os.getenv("CHAT_PROVIDER", "openai")

    # Embeddings settings
    EMBEDDINGS_PROVIDER: str = os.getenv("EMBEDDINGS_PROVIDER", "openai")

    # MinIO settings
    MINIO_ENDPOINT: str = os.getenv("MINIO_ENDPOINT", "localhost:9000")
    MINIO_ACCESS_KEY: str = os.getenv("MINIO_ACCESS_KEY", "minioadmin")
    MINIO_SECRET_KEY: str = os.getenv("MINIO_SECRET_KEY", "minioadmin")
    MINIO_BUCKET_NAME: str = os.getenv("MINIO_BUCKET_NAME", "documents")

    # Shared model API key fallback
    API_KEY: str = os.getenv("API_KEY", "")

    # OpenAI settings
    OPENAI_API_BASE: str = os.getenv("OPENAI_API_BASE", "https://api.openai.com/v1")
    OPENAI_API_KEY: str = os.getenv("OPENAI_API_KEY", os.getenv("API_KEY", ""))
    OPENAI_MODEL: str = os.getenv("OPENAI_MODEL", "gpt-4")
    OPENAI_EMBEDDINGS_MODEL: str = os.getenv("OPENAI_EMBEDDINGS_MODEL", "text-embedding-ada-002")

    # DashScope settings
    DASH_SCOPE_API_KEY: str = os.getenv(
        "DASH_SCOPE_API_KEY",
        os.getenv("DASHSCOPE_API_KEY", os.getenv("API_KEY", "")),
    )
    DASH_SCOPE_API_BASE: str = os.getenv(
        "DASH_SCOPE_API_BASE", "https://dashscope.aliyuncs.com/compatible-mode/v1"
    )
    DASH_SCOPE_CHAT_MODEL: str = os.getenv("DASH_SCOPE_CHAT_MODEL", "qwen3-max")
    DASH_SCOPE_EMBEDDINGS_MODEL: str = os.getenv("DASH_SCOPE_EMBEDDINGS_MODEL", "text-embedding-v4")

    # Vector Store settings
    VECTOR_STORE_TYPE: str = os.getenv("VECTOR_STORE_TYPE", "chroma")

    # External reranker settings
    RERANKER_API_URL: str = os.getenv("RERANKER_API_URL", "")
    RERANKER_API_KEY: str = os.getenv(
        "RERANKER_API_KEY",
        os.getenv(
            "DASH_SCOPE_API_KEY",
            os.getenv("DASHSCOPE_API_KEY", os.getenv("API_KEY", "")),
        ),
    )
    RERANKER_MODEL: str = os.getenv("RERANKER_MODEL", "")
    RERANKER_TIMEOUT_SECONDS: float = float(os.getenv("RERANKER_TIMEOUT_SECONDS", "8"))
    RERANKER_WEIGHT: float = float(os.getenv("RERANKER_WEIGHT", "0.75"))

    # GraphRAG settings
    GRAPHRAG_ENABLED: bool = os.getenv("GRAPHRAG_ENABLED", "false").lower() == "true"
    GRAPHRAG_WORKING_DIR: str = os.getenv("GRAPHRAG_WORKING_DIR", "./graphrag_cache")
    GRAPHRAG_GRAPH_STORAGE: str = os.getenv("GRAPHRAG_GRAPH_STORAGE", "neo4j")
    GRAPHRAG_QUERY_LEVEL: int = int(os.getenv("GRAPHRAG_QUERY_LEVEL", "2"))
    GRAPHRAG_LOCAL_TOP_K: int = int(os.getenv("GRAPHRAG_LOCAL_TOP_K", "20"))
    GRAPHRAG_ENTITY_EXTRACT_MAX_GLEANING: int = int(os.getenv("GRAPHRAG_ENTITY_EXTRACT_MAX_GLEANING", "1"))
    GRAPHRAG_EMBEDDING_DIM: int = int(os.getenv("GRAPHRAG_EMBEDDING_DIM", "1024"))
    GRAPHRAG_EMBEDDING_MAX_TOKEN_SIZE: int = int(os.getenv("GRAPHRAG_EMBEDDING_MAX_TOKEN_SIZE", "8192"))

    # Neo4j settings
    NEO4J_URL: str = os.getenv("NEO4J_URL", "bolt://localhost:7687")
    NEO4J_USERNAME: str = os.getenv("NEO4J_USERNAME", "neo4j")
    NEO4J_PASSWORD: str = os.getenv("NEO4J_PASSWORD", "neo4j")

    # Chroma DB settings
    CHROMA_DB_HOST: str = os.getenv("CHROMA_DB_HOST", "chromadb")
    CHROMA_DB_PORT: int = int(os.getenv("CHROMA_DB_PORT", "8000"))

    # Qdrant DB settings
    QDRANT_URL: str = os.getenv("QDRANT_URL", "http://localhost:6333")
    QDRANT_PREFER_GRPC: bool = os.getenv("QDRANT_PREFER_GRPC", "true").lower() == "true"

    # Deepseek settings
    DEEPSEEK_API_KEY: str = ""
    DEEPSEEK_API_BASE: str = "https://api.deepseek.com/v1"  # 默认 API 地址
    DEEPSEEK_MODEL: str = "deepseek-chat"  # 默认模型名称

    # Ollama settings
    OLLAMA_API_BASE: str = "http://localhost:11434"
    OLLAMA_MODEL: str = "deepseek-r1:7b"
    OLLAMA_EMBEDDINGS_MODEL: str = os.getenv(
        "OLLAMA_EMBEDDINGS_MODEL", "nomic-embed-text"
    )  # Added this line

    class Config:
        env_file = ".env"


settings = Settings()
if not settings.SECRET_KEY:
    if settings.ENVIRONMENT.lower() in {"prod", "production"}:
        raise ValueError("SECRET_KEY must be set in production.")
    settings.SECRET_KEY = secrets.token_urlsafe(32)
