import os
from datetime import timedelta
from pathlib import Path

from dotenv import load_dotenv
from sqlalchemy.pool import NullPool

BASE_DIR = Path(__file__).resolve().parent
# Allow hosting-panel environment variables to take precedence over the local .env file.
load_dotenv(BASE_DIR / ".env", override=False)

INSTANCE_DIR = Path(os.getenv("INSTANCE_PATH", BASE_DIR / "instance")).resolve()
DATA_ROOT = Path(os.getenv("DATA_ROOT", INSTANCE_DIR / "data")).resolve()
DEFAULT_UPLOAD_ROOT = Path(os.getenv("UPLOAD_ROOT", DATA_ROOT / "uploads")).resolve()
DEFAULT_TEMP_UPLOAD_DIR = Path(os.getenv("TEMP_UPLOAD_DIR", DATA_ROOT / "tmp")).resolve()
DEFAULT_LOG_DIR = Path(os.getenv("LOG_DIR", DATA_ROOT / "logs")).resolve()
DEFAULT_DATABASE_URL = os.getenv(
    "DATABASE_URL",
    "mysql+pymysql://root:root@127.0.0.1:3306/ticketing_system",
)
NAMECHEAP_SAFE_UPLOAD_EXTENSIONS = [
    "log",
    "txt",
    "zip",
    "pdf",
    "png",
    "jpg",
    "jpeg",
    "doc",
    "docx",
    "xls",
    "xlsx",
    "csv",
]


def _env_list(name: str, default: str) -> list[str]:
    return [item.strip().lower() for item in os.getenv(name, default).split(",") if item.strip()]


def _env_int(name: str, default: int) -> int:
    return int(os.getenv(name, str(default)))


def _env_bool(name: str, default: bool) -> bool:
    return os.getenv(name, "1" if default else "0").strip().lower() in {"1", "true", "yes", "on"}


def _capped_env_int(name: str, default: int, maximum: int) -> int:
    return min(_env_int(name, default), maximum)


def _strict_extension_list(name: str, fallback: list[str]) -> list[str]:
    configured = _env_list(name, ",".join(fallback))
    if not configured or any(item in {"*", "*.*", "all"} for item in configured):
        return fallback
    return configured


def _database_engine_options(database_uri: str, *, shared_default: bool = True) -> dict:
    if database_uri.startswith("sqlite"):
        return {}

    options = {
        "pool_pre_ping": True,
        "pool_recycle": _env_int("DB_POOL_RECYCLE", 280),
    }
    pool_class = os.getenv("DB_POOL_CLASS", "queue").strip().lower()
    if pool_class == "null":
        options["poolclass"] = NullPool
        return options

    options["pool_size"] = _env_int("DB_POOL_SIZE", 2 if shared_default else 5)
    options["max_overflow"] = _env_int("DB_MAX_OVERFLOW", 1 if shared_default else 10)
    options["pool_timeout"] = _env_int("DB_POOL_TIMEOUT", 30)
    return options


class BaseConfig:
    APP_NAME = os.getenv("APP_NAME", "KHF SMP")
    APP_LOGO_URL = os.getenv("APP_LOGO_URL", "/static/img/brand-logo.svg")
    AUTH_LOGO_URL = os.getenv("AUTH_LOGO_URL", APP_LOGO_URL)
    SECRET_KEY = os.getenv("SECRET_KEY", "change-me")
    SQLALCHEMY_DATABASE_URI = DEFAULT_DATABASE_URL
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    SQLALCHEMY_ENGINE_OPTIONS = _database_engine_options(SQLALCHEMY_DATABASE_URI, shared_default=True)
    INSTANCE_PATH = str(INSTANCE_DIR)
    DATA_ROOT = str(DATA_ROOT)
    UPLOAD_ROOT = str(DEFAULT_UPLOAD_ROOT)
    FILE_STORAGE_PATH = os.getenv("FILE_STORAGE_PATH", str(DEFAULT_UPLOAD_ROOT))
    TEMP_UPLOAD_DIR = str(DEFAULT_TEMP_UPLOAD_DIR)
    LOG_DIR = str(DEFAULT_LOG_DIR)
    MAX_UPLOAD_SIZE_MB = _env_int("MAX_UPLOAD_SIZE_MB", 256)
    MAX_CONTENT_LENGTH = MAX_UPLOAD_SIZE_MB * 1024 * 1024
    MAX_UPLOAD_FILES_PER_REQUEST = _env_int("MAX_UPLOAD_FILES_PER_REQUEST", 20)
    MAX_UPLOAD_BATCH_SIZE_MB = _env_int("MAX_UPLOAD_BATCH_SIZE_MB", MAX_UPLOAD_SIZE_MB)
    MAX_UPLOAD_FILENAME_LENGTH = _env_int("MAX_UPLOAD_FILENAME_LENGTH", 180)
    ALLOWED_UPLOAD_EXTENSIONS = _env_list(
        "ALLOWED_UPLOAD_EXTENSIONS",
        "log,txt,zip,pdf,png,jpg,jpeg,doc,docx,xlsx",
    )
    BLOCKED_UPLOAD_EXTENSIONS = _env_list(
        "BLOCKED_UPLOAD_EXTENSIONS",
        "exe,dll,so,bin,msi,bat,cmd,com,ps1,sh,php,php3,php4,php5,phtml,phar,pl,py,cgi,jar,war,htaccess,env,ini",
    )
    STRICT_SHARED_UPLOAD_POLICY = _env_bool("STRICT_SHARED_UPLOAD_POLICY", False)
    LOCKED_SETTING_KEYS: tuple[str, ...] = ()
    SESSION_COOKIE_HTTPONLY = True
    SESSION_COOKIE_SAMESITE = "Lax"
    REMEMBER_COOKIE_HTTPONLY = True
    REMEMBER_COOKIE_DURATION = timedelta(days=14)
    SESSION_COOKIE_SECURE = _env_bool("SESSION_COOKIE_SECURE", True)
    REMEMBER_COOKIE_SECURE = _env_bool("REMEMBER_COOKIE_SECURE", True)
    SESSION_TIMEOUT_MINUTES = _env_int("SESSION_TIMEOUT_MINUTES", 30)
    SESSION_ABSOLUTE_TIMEOUT_MINUTES = _env_int("SESSION_ABSOLUTE_TIMEOUT_MINUTES", 240)
    SESSION_BIND_IP = _env_bool("SESSION_BIND_IP", True)
    SESSION_BIND_USER_AGENT = _env_bool("SESSION_BIND_USER_AGENT", True)
    SESSION_REFRESH_EACH_REQUEST = True
    PERMANENT_SESSION_LIFETIME = timedelta(minutes=SESSION_TIMEOUT_MINUTES)
    WTF_CSRF_TIME_LIMIT = 7200
    RATELIMIT_STORAGE_URI = "memory://"
    ACCOUNT_LOCK_ATTEMPTS = _env_int("ACCOUNT_LOCK_ATTEMPTS", 5)
    ACCOUNT_LOCK_MINUTES = _env_int("ACCOUNT_LOCK_MINUTES", 30)
    PASSWORD_RESET_SALT = "password-reset"
    PASSWORD_MIN_LENGTH = _env_int("PASSWORD_MIN_LENGTH", 12)
    MFA_ISSUER = os.getenv("MFA_ISSUER", APP_NAME)
    MFA_CODE_VALID_WINDOW = _env_int("MFA_CODE_VALID_WINDOW", 1)
    MFA_PENDING_MINUTES = _env_int("MFA_PENDING_MINUTES", 5)
    MFA_CODE_TTL_MINUTES = _env_int("MFA_CODE_TTL_MINUTES", 5)
    MFA_RESEND_INTERVAL_SECONDS = _env_int("MFA_RESEND_INTERVAL_SECONDS", 45)
    DEFAULT_TICKET_PREFIX = os.getenv("TICKET_NUMBER_PREFIX", "TKT")
    DEFAULT_PAGE_SIZE = 20
    MAX_PAGE_SIZE = 100
    BRAND_COLOR = "#17465f"
    APPLICATION_ROOT = os.getenv("APPLICATION_ROOT", "/")
    PREFERRED_URL_SCHEME = os.getenv("PREFERRED_URL_SCHEME", "https")
    TRUST_PROXY_FIX = _env_bool("TRUST_PROXY_FIX", True)
    FILE_LOG_LEVEL = os.getenv("FILE_LOG_LEVEL", "INFO")
    MAIL_HOST = os.getenv("MAIL_HOST", os.getenv("SMTP_HOST", ""))
    MAIL_PORT = _env_int("MAIL_PORT", _env_int("SMTP_PORT", 587))
    MAIL_USERNAME = os.getenv("MAIL_USERNAME", os.getenv("SMTP_USERNAME", ""))
    MAIL_PASSWORD = os.getenv("MAIL_PASSWORD", os.getenv("SMTP_PASSWORD", ""))
    MAIL_FROM_ADDRESS = os.getenv("MAIL_FROM_ADDRESS", MAIL_USERNAME or "no-reply@example.com")
    MAIL_FROM_NAME = os.getenv("MAIL_FROM_NAME", APP_NAME)
    MAIL_USE_TLS = _env_bool("MAIL_USE_TLS", True)
    MAIL_USE_SSL = _env_bool("MAIL_USE_SSL", False)
    EMAIL_NOTIFICATIONS_ENABLED = _env_bool("EMAIL_NOTIFICATIONS_ENABLED", True)
    TELEGRAM_NOTIFICATIONS_ENABLED = _env_bool("TELEGRAM_NOTIFICATIONS_ENABLED", False)
    TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN", "")
    TELEGRAM_BOT_USERNAME = os.getenv("TELEGRAM_BOT_USERNAME", "")
    TELEGRAM_WEBHOOK_SECRET = os.getenv("TELEGRAM_WEBHOOK_SECRET", "")
    TELEGRAM_LINK_TTL_MINUTES = _env_int("TELEGRAM_LINK_TTL_MINUTES", 30)
    AUTH_DEBUG_FALLBACKS = _env_bool("AUTH_DEBUG_FALLBACKS", False)
    SUPPORTED_LOCALES = ("en", "ar")


class DevelopmentConfig(BaseConfig):
    DEBUG = True
    SESSION_COOKIE_SECURE = _env_bool("SESSION_COOKIE_SECURE", False)
    REMEMBER_COOKIE_SECURE = _env_bool("REMEMBER_COOKIE_SECURE", False)
    PREFERRED_URL_SCHEME = os.getenv("PREFERRED_URL_SCHEME", "http")
    SESSION_BIND_IP = _env_bool("SESSION_BIND_IP", False)
    SESSION_BIND_USER_AGENT = _env_bool("SESSION_BIND_USER_AGENT", False)
    SQLALCHEMY_ENGINE_OPTIONS = _database_engine_options(DEFAULT_DATABASE_URL, shared_default=False)


class TestingConfig(BaseConfig):
    TESTING = True
    WTF_CSRF_ENABLED = False
    SESSION_COOKIE_SECURE = False
    REMEMBER_COOKIE_SECURE = False
    SESSION_BIND_IP = False
    SESSION_BIND_USER_AGENT = False
    SQLALCHEMY_DATABASE_URI = os.getenv("TEST_DATABASE_URL", "sqlite+pysqlite:///:memory:")
    SQLALCHEMY_ENGINE_OPTIONS = {}


class ProductionConfig(BaseConfig):
    DEBUG = False
    SESSION_COOKIE_SECURE = True
    REMEMBER_COOKIE_SECURE = True


class SharedHostingConfig(ProductionConfig):
    DEBUG = False
    SQLALCHEMY_ENGINE_OPTIONS = _database_engine_options(DEFAULT_DATABASE_URL, shared_default=True)


class NamecheapConfig(SharedHostingConfig):
    MAX_UPLOAD_SIZE_MB = _capped_env_int("MAX_UPLOAD_SIZE_MB", 32, 32)
    MAX_CONTENT_LENGTH = MAX_UPLOAD_SIZE_MB * 1024 * 1024
    MAX_UPLOAD_FILES_PER_REQUEST = _capped_env_int("MAX_UPLOAD_FILES_PER_REQUEST", 10, 10)
    MAX_UPLOAD_BATCH_SIZE_MB = _capped_env_int("MAX_UPLOAD_BATCH_SIZE_MB", 96, 96)
    ALLOWED_UPLOAD_EXTENSIONS = _strict_extension_list("ALLOWED_UPLOAD_EXTENSIONS", NAMECHEAP_SAFE_UPLOAD_EXTENSIONS)
    STRICT_SHARED_UPLOAD_POLICY = _env_bool("STRICT_SHARED_UPLOAD_POLICY", True)
    LOCKED_SETTING_KEYS = ("file_storage_path", "max_upload_size_mb", "allowed_upload_extensions")


config_map = {
    "development": DevelopmentConfig,
    "testing": TestingConfig,
    "production": ProductionConfig,
    "shared": SharedHostingConfig,
    "namecheap": NamecheapConfig,
}
