"""
Конфигурация проекта из переменных окружения (.env).

Читает настройки через python-dotenv, предоставляет единый интерфейс
ко всем учётным данным и параметрам.

Пример:
    from config import config
    print(config.tbank_token)
    print(config.db_host)
"""

import os
from dataclasses import dataclass, field
from pathlib import Path
from typing import Optional


def _load_dotenv():
    """Загрузить .env файл если python-dotenv доступен."""
    try:
        from dotenv import load_dotenv
        # Ищем .env сначала рядом с config.py, потом в корне проекта
        env_path = Path(__file__).parent / ".env"
        if not env_path.exists():
            env_path = Path(__file__).parent.parent.parent / ".env"
        if env_path.exists():
            load_dotenv(env_path)
    except ImportError:
        pass


_load_dotenv()


def _float_env(key: str, default: float) -> float:
    val = os.environ.get(key, "")
    try:
        return float(val)
    except (ValueError, TypeError):
        return default


def _int_env(key: str, default: int) -> int:
    val = os.environ.get(key, "")
    try:
        return int(val)
    except (ValueError, TypeError):
        return default


@dataclass
class ProjectConfig:
    """Единая конфигурация проекта."""

    # ── T-Bank API ────────────────────────────────────────
    # Режим работы: 'sandbox' (по умолчанию) или 'real'
    tbank_env: str = field(default_factory=lambda: os.environ.get(
        "TBANK_ENV", "sandbox"
    ))
    # Sandbox (песочница) — используется по умолчанию для чтения данных
    tbank_token: str = field(default_factory=lambda: os.environ.get(
        "TBANK_TOKEN",
        "t.wqnyx3rg3L8_P3GUrXXP29SPdebJRvYYD5b_Z5-5PjA1ky5_jJRaQlZRVV6eYe60WxuQBHzUI7RgxJpJskj_8g",
    ))
    tbank_base_url: str = field(default_factory=lambda: os.environ.get(
        "TBANK_BASE_URL",
        "https://sandbox-invest-public-api.tinkoff.ru/rest",
    ))
    tbank_account_id: str = field(default_factory=lambda: os.environ.get(
        "TBANK_ACCOUNT_ID", ""
    ))
    # Реальный счёт (боевой)
    tbank_real_token: str = field(default_factory=lambda: os.environ.get(
        "TBANK_REAL_TOKEN", ""
    ))
    tbank_real_base_url: str = field(default_factory=lambda: os.environ.get(
        "TBANK_REAL_BASE_URL",
        "https://invest-public-api.tinkoff.ru/rest",
    ))
    tbank_account_id_real: str = field(default_factory=lambda: os.environ.get(
        "TBANK_ACCOUNT_ID_REAL", ""
    ))

    @property
    def active_token(self) -> str:
        """Токен активного окружения (sandbox/real)."""
        if self.tbank_env == "real":
            return self.tbank_real_token or self.tbank_token
        return self.tbank_token

    @property
    def active_base_url(self) -> str:
        """Базовый URL активного окружения (sandbox/real)."""
        if self.tbank_env == "real":
            return self.tbank_real_base_url
        return self.tbank_base_url

    @property
    def active_account_id(self) -> str:
        """ID счёта активного окружения (sandbox/real)."""
        if self.tbank_env == "real":
            return self.tbank_account_id_real or self.tbank_account_id
        return self.tbank_account_id

    # ── Комиссии ──────────────────────────────────────────
    # Акции/облигации/ETF: брокер 0.3% (биржа включена в тариф)
    tbank_commission_pct: float = field(default_factory=lambda: _float_env(
        "TBANK_COMMISSION_PCT", 0.3
    ))
    moex_exchange_fee_pct: float = field(default_factory=lambda: _float_env(
        "MOEX_EXCHANGE_FEE_PCT", 0.0
    ))
    # Фьючерсы: 0.1% от стоимости контракта
    tbank_futures_commission_pct: float = field(default_factory=lambda: _float_env(
        "TBANK_FUTURES_COMMISSION_PCT", 0.1
    ))
    # Опционы: 3% за сделку, минимум 0.02 ₽ за контракт
    tbank_options_commission_pct: float = field(default_factory=lambda: _float_env(
        "TBANK_OPTIONS_COMMISSION_PCT", 3.0
    ))
    tbank_options_min_per_contract: float = field(default_factory=lambda: _float_env(
        "TBANK_OPTIONS_MIN_PER_CONTRACT", 0.02
    ))

    @property
    def total_one_way_pct(self) -> float:
        return round(self.tbank_commission_pct + self.moex_exchange_fee_pct, 4)

    @property
    def total_roundtrip_pct(self) -> float:
        return round(self.total_one_way_pct * 2, 4)

    # ── База данных ───────────────────────────────────────
    db_host: str = field(default_factory=lambda: os.environ.get(
        "DB_HOST", "nlbotinterface.ru"
    ))
    db_port: int = field(default_factory=lambda: _int_env("DB_PORT", 3306))
    db_name: str = field(default_factory=lambda: os.environ.get(
        "DB_NAME", "bitcoin_tickers"
    ))
    db_user: str = field(default_factory=lambda: os.environ.get(
        "DB_USER", "bitcoin"
    ))
    db_password: str = field(default_factory=lambda: os.environ.get(
        "DB_PASSWORD", "g49020007"
    ))

    @property
    def db_config(self) -> dict:
        """Словарь для mysql.connector.connect()."""
        return {
            "host": self.db_host,
            "port": self.db_port,
            "database": self.db_name,
            "user": self.db_user,
            "password": self.db_password,
            "autocommit": True,
            "charset": "utf8mb4",
        }

    # ── MOEX ──────────────────────────────────────────────
    moex_price_steps: list = field(default_factory=lambda: [
        (500, 0.01),
        (5000, 0.5),
        (float("inf"), 1.0),
    ])

    moex_lot_sizes: dict = field(default_factory=lambda: {
        "GAZP": 10,
    })


# Глобальный экземпляр
config = ProjectConfig()
