import os
from pathlib import Path
from typing import List, Optional

from dotenv import load_dotenv


PROJECT_ROOT = Path(__file__).resolve().parents[1]
ENV_FILE = PROJECT_ROOT / ".env"
load_dotenv(dotenv_path=ENV_FILE)


def _env_bool(name: str, default: bool = False) -> bool:
    value = os.getenv(name)
    if value is None:
        return default
    return value.strip().lower() in {"1", "true", "yes", "on"}


def _env_int(name: str, default: int, minimum: Optional[int] = None) -> int:
    raw_value = os.getenv(name)
    try:
        value = int(raw_value) if raw_value is not None else default
    except (TypeError, ValueError):
        value = default
    if minimum is not None:
        value = max(minimum, value)
    return value


def _env_float(
    name: str,
    default: float,
    minimum: Optional[float] = None,
    maximum: Optional[float] = None,
) -> float:
    raw_value = os.getenv(name)
    try:
        value = float(raw_value) if raw_value is not None else default
    except (TypeError, ValueError):
        value = default
    if minimum is not None:
        value = max(minimum, value)
    if maximum is not None:
        value = min(maximum, value)
    return value


def _env_list(name: str, default: List[str]) -> List[str]:
    raw_value = os.getenv(name)
    if not raw_value:
        return list(default)
    values = [item.strip() for item in raw_value.split(",") if item.strip()]
    return values or list(default)


class Settings:
    """Application settings loaded from environment variables."""

    APP_NAME: str = os.getenv("APP_NAME", "Phitagoras AI Chatbot Engine")
    APP_VERSION: str = os.getenv("APP_VERSION", "1.1.1")
    DEBUG: bool = _env_bool("DEBUG", False)

    HOST: str = os.getenv("HOST", "0.0.0.0")
    PORT: int = _env_int("PORT", 8000, minimum=1)

    FRONTEND_URL: str = os.getenv("FRONTEND_URL", "http://localhost:8000")
    ALLOWED_ORIGINS: List[str] = _env_list(
        "ALLOWED_ORIGINS",
        [
            "http://localhost",
            "http://localhost:3000",
            FRONTEND_URL,
        ],
    )
    ALLOW_CREDENTIALS: bool = _env_bool("ALLOW_CREDENTIALS", True)
    ALLOW_METHODS: List[str] = _env_list(
        "ALLOW_METHODS",
        ["GET", "POST", "OPTIONS"],
    )
    ALLOW_HEADERS: List[str] = _env_list(
        "ALLOW_HEADERS",
        ["Content-Type", "Authorization", "X-API-Key"],
    )

    MODEL_PATH: str = os.getenv("MODEL_PATH", "app/model")
    INTENTS_PATH: str = os.getenv("INTENTS_PATH", "app/data/intents.json")

    CONFIDENCE_THRESHOLD: float = _env_float(
        "CONFIDENCE_THRESHOLD",
        0.20,
        minimum=0.0,
        maximum=1.0,
    )
    MIN_CONFIDENCE_MARGIN: float = _env_float(
        "MIN_CONFIDENCE_MARGIN",
        0.03,
        minimum=0.0,
        maximum=1.0,
    )

    GEMINI_ENABLED: bool = _env_bool("GEMINI_ENABLED", False)
    GEMINI_API_KEY: Optional[str] = os.getenv("GEMINI_API_KEY")
    GEMINI_MODEL: str = os.getenv("GEMINI_MODEL", "gemini-3.6-flash")
    GEMINI_THINKING_LEVEL: str = os.getenv(
        "GEMINI_THINKING_LEVEL",
        "minimal",
    ).strip().lower()
    GEMINI_MAX_OUTPUT_TOKENS: int = _env_int(
        "GEMINI_MAX_OUTPUT_TOKENS",
        1024,
        minimum=128,
    )
    GEMINI_MAX_OUTPUT_CHARACTERS: int = _env_int(
        "GEMINI_MAX_OUTPUT_CHARACTERS",
        1800,
        minimum=200,
    )
    GEMINI_TIMEOUT_SECONDS: int = _env_int(
        "GEMINI_TIMEOUT_SECONDS",
        25,
        minimum=1,
    )
    GEMINI_CONTEXT_TOP_K: int = _env_int(
        "GEMINI_CONTEXT_TOP_K",
        3,
        minimum=1,
    )
    GEMINI_MIN_CLASSIFIER_CONFIDENCE: float = _env_float(
        "GEMINI_MIN_CLASSIFIER_CONFIDENCE",
        0.05,
        minimum=0.0,
        maximum=1.0,
    )
    GEMINI_FALLBACK_ON_LOW_CONFIDENCE: bool = _env_bool(
        "GEMINI_FALLBACK_ON_LOW_CONFIDENCE",
        True,
    )
    GEMINI_FALLBACK_ON_AMBIGUOUS: bool = _env_bool(
        "GEMINI_FALLBACK_ON_AMBIGUOUS",
        True,
    )

    GEMINI_PROJECT_NAME: Optional[str] = os.getenv("GEMINI_PROJECT_NAME")
    GEMINI_PROJECT_NUMBER: Optional[str] = os.getenv("GEMINI_PROJECT_NUMBER")

    RATE_LIMIT_ENABLED: bool = _env_bool("RATE_LIMIT_ENABLED", True)
    RATE_LIMIT_REQUESTS: int = _env_int(
        "RATE_LIMIT_REQUESTS",
        10,
        minimum=1,
    )
    RATE_LIMIT_WINDOW: int = _env_int(
        "RATE_LIMIT_WINDOW",
        60,
        minimum=1,
    )

    LOG_LEVEL: str = os.getenv("LOG_LEVEL", "INFO").upper()
    LOG_FILE: Optional[str] = os.getenv("LOG_FILE")

    API_KEY: Optional[str] = os.getenv("API_KEY")
    REQUIRE_API_KEY: bool = _env_bool("REQUIRE_API_KEY", False)

    DATABASE_URL: Optional[str] = os.getenv("DATABASE_URL")

    @classmethod
    def get_settings(cls) -> "Settings":
        return cls()

    @classmethod
    def validate_runtime(cls) -> List[str]:
        warnings: List[str] = []

        if cls.GEMINI_ENABLED and not cls.GEMINI_API_KEY:
            warnings.append(
                "GEMINI_ENABLED=True tetapi GEMINI_API_KEY belum diatur."
            )

        if cls.GEMINI_THINKING_LEVEL not in {
            "minimal",
            "low",
            "medium",
            "high",
        }:
            warnings.append(
                "GEMINI_THINKING_LEVEL harus minimal, low, medium, atau high."
            )

        if cls.REQUIRE_API_KEY and not cls.API_KEY:
            warnings.append(
                "REQUIRE_API_KEY=True tetapi API_KEY belum diatur."
            )

        if "*" in cls.ALLOWED_ORIGINS and cls.ALLOW_CREDENTIALS:
            warnings.append(
                "CORS wildcard tidak aman ketika credentials diaktifkan."
            )

        return warnings


settings = Settings.get_settings()