import os
from pathlib import Path
from typing import Literal

from pydantic import Field, field_validator
from pydantic_settings import BaseSettings

from common_logging import get_logger

logger = get_logger(__name__)

PROJECT_ROOT = Path(__file__).resolve().parents[2]
LLM_SERVICE_DIR = PROJECT_ROOT / "llm_service"
DEFAULT_BASE_MODELS_DIR = LLM_SERVICE_DIR / "base_models"
DEFAULT_TRAINED_MODELS_DIR = LLM_SERVICE_DIR / "trained_models"


class Settings(BaseSettings):
    ENVIRONMENT: Literal["development", "staging", "production"] = "production"
    PROJECT_NAME: str = "HelloTax AI"
    API_V1_STR: str = "/api/v1"
    SECRET_KEY: str = "your-secret-key-change-this-in-production"
    ALGORITHM: str = "HS256"
    ACCESS_TOKEN_EXPIRE_MINUTES: int = 480
    CORS_ORIGINS: list[str] = Field(
        default_factory=lambda: [
            "http://localhost:8500",
            "http://localhost:8888",
            "http://ai.leshuiyun.com",
            "http://training.leshuiyun.com",
            "https://ai.leshuiyun.com",
            "https://training.leshuiyun.com",
        ]
    )
    CORS_METHODS: list[str] = Field(
        default_factory=lambda: ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"]
    )
    CORS_HEADERS: list[str] = Field(default_factory=lambda: ["*"])

    @field_validator("SECRET_KEY")
    @classmethod
    def validate_secret_key(cls, v: str, info) -> str:
        if info.data.get("ENVIRONMENT") == "production":
            if v in ["your-secret-key-change-this-in-production", ""]:
                logger.error("SECRET_KEY validation failed: using default value in production")
                raise ValueError("SECRET_KEY must be changed from default value in production")
        if len(v) < 32:
            logger.error(f"SECRET_KEY validation failed: length {len(v)} < 32")
            raise ValueError("SECRET_KEY must be at least 32 characters")
        logger.info("SECRET_KEY validation passed")
        return v

    ENVIRONMENT: Literal["development", "staging", "production"] = "production"
    RATE_LIMIT_ENABLED: bool = True
    RATE_LIMIT_PER_MINUTE: int = 60
    RATE_LIMIT_PER_HOUR: int = 1000
    DATABASE_URL: str = "postgresql+psycopg2://user:pass@localhost:5432/base_platform"
    DATA_CENTER_DATABASE_URL: str | None = None

    @field_validator("DATABASE_URL")
    @classmethod
    def validate_database_url(cls, v: str, info) -> str:
        if info.data.get("ENVIRONMENT") == "production":
            if "pass" in v or "password" in v.split("@")[0].split(":")[-1]:
                logger.error("DATABASE_URL validation failed: using default password in production")
                raise ValueError("DATABASE_URL must not contain default password in production")
        logger.info("DATABASE_URL validation passed")
        return v

    BASE_MODELS_DIR: str = str(DEFAULT_BASE_MODELS_DIR)
    TRAINED_MODELS_DIR: str = str(DEFAULT_TRAINED_MODELS_DIR)
    BASE_PLATFORM_UVICORN_RELOAD: bool = False
    LOCAL_BGE_DEVICE: str = "cpu"
    LOCAL_BGE_BATCH_SIZE: int = 4
    LOCAL_BGE_MAX_LENGTH: int = 1024
    LOCAL_BGE_AUTO_UNLOAD: bool = True
    LOCAL_BGE_RERANKER_DEVICE: str = "cpu"
    LOCAL_BGE_RERANKER_BATCH_SIZE: int = 4
    LOCAL_BGE_RERANKER_MAX_LENGTH: int = 256
    LOCAL_BGE_RERANKER_AUTO_UNLOAD: bool = False
    LOCAL_CHAT_SINGLE_MODEL_CACHE: bool = True
    OPENAI_API_KEY: str | None = None
    OPENAI_BASE_URL: str | None = None
    VECTOR_STORE_TYPE: str = "milvus"
    MILVUS_HOST: str = "localhost"
    MILVUS_PORT: str = "19530"
    USE_MILVUS_LITE: bool = False
    MINIO_ENDPOINT: str = "localhost:9000"
    MINIO_ACCESS_KEY: str = "minioadmin"
    MINIO_SECRET_KEY: str = "minioadmin"
    MINIO_SECURE: str = "false"
    MINIO_BUCKET: str = "knowledge-documents"
    SMTP_HOST: str = "smtp.gmail.com"
    SMTP_PORT: int = 587
    SMTP_USER: str = ""
    SMTP_PASSWORD: str = ""
    SMTP_FROM: str = ""
    SMTP_FROM_NAME: str = "HelloTax AI"
    FRONTEND_URL: str = "http://localhost:8888"
    DEV_MODE: bool = False
    NEO4J_URI: str = "bolt://localhost:7687"
    NEO4J_USER: str = "neo4j"
    NEO4J_PASSWORD: str = "password"
    NEO4J_DATABASE: str = "neo4j"

    @field_validator("NEO4J_PASSWORD")
    @classmethod
    def validate_neo4j_password(cls, v: str, info) -> str:
        if info.data.get("ENVIRONMENT") == "production":
            if v == "password":
                logger.error("NEO4J_PASSWORD validation failed: using default password in production")
                raise ValueError("NEO4J_PASSWORD must be changed from default in production")
        logger.info("NEO4J_PASSWORD validation passed")
        return v

    ENABLE_KNOWLEDGE_GRAPH: bool = True
    GRAPH_AUTO_BUILD: bool = True
    GRAPH_EXPAND_DEPTH: int = 1
    GRAPH_ENTITY_EXTRACTION_MODEL: str = "gpt-4"
    GRAPH_MIN_ENTITY_CONFIDENCE: float = 0.7
    GRAPH_CACHE_TTL: int = 3600
    ENABLE_AGENTIC_RAG: bool = True
    AGENTIC_RAG_MAX_QUERIES: int = 3
    AGENTIC_RAG_INTENT_TEMPERATURE: float = 0.3
    AGENTIC_RAG_INTENT_MAX_TOKENS: int = 300
    ENABLE_BGE_RERANKER: bool = True
    BGE_RERANKER_MODEL: str = "local-bge-reranker"
    BGE_RERANKER_INITIAL_K: int = 30
    BGE_RERANKER_FINAL_K: int = 5
    REDIS_URL: str | None = None
    REDIS_HOST: str = "localhost"
    REDIS_PORT: int = 6379
    REDIS_DB: int = 0
    REDIS_PASSWORD: str | None = None
    ENCRYPTION_KEY: str | None = None
    INTERNAL_API_TOKEN: str | None = None
    SWITCH_MODE_SCRIPT: str = "/lsinfo/ai/hellotax_ai/scripts/llm/switch_mode.sh"
    TRAFFIC_MONITORING_ENABLED: bool = True
    TRAFFIC_STATS_RETENTION_HOURS: int = 24
    TRAFFIC_REDIS_KEY_PREFIX: str = "traffic:"
    GZIP_COMPRESSION_ENABLED: bool = True
    GZIP_MINIMUM_SIZE: int = 1000
    USE_ORJSON: bool = True

    class Config:
        env_file = f".env.{os.environ.get('APP_ENV', 'development')}"
        case_sensitive = True
        validate_assignment = True
        extra = "ignore"
        extra = "ignore"


BASE_PLATFORM_ROOT = Path(__file__).resolve().parents[1]
settings = Settings(_env_file=str(BASE_PLATFORM_ROOT / f".env.{os.environ.get('APP_ENV', 'development')}"))
