# app/extensions.py

import logging
import os
import redis
from flask_talisman import Talisman
from flask_session import Session
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
from flask_wtf import CSRFProtect
from flask_login import LoginManager, UserMixin
from app.database import get_db_connection
from flask_sqlalchemy import SQLAlchemy
from flask_apscheduler import APScheduler
talisman  = Talisman()
db = SQLAlchemy()
scheduler  = APScheduler()
def init_extensions(app):
    scheduler.init_app(app)
    scheduler.start()
    Talisman(app, content_security_policy=app.config["TALISMAN_CSP"])


def logger_init(app):
    """Инициализация логгера."""
    log_path = os.path.join(os.path.dirname(__file__), "..", "logs")
    if not os.path.exists(log_path):
        os.makedirs(log_path)

    logging.basicConfig(
        filename=os.path.join(log_path, "errors.log"),
        level=logging.DEBUG,
        format="%(asctime)s %(levelname)s: %(message)s"
    )
    app.logger.info("Logger initialized")

def db_init(app):
    db.init_app(app)
    with app.app_context():
        db.create_all()

# “экземпляры” расширений
csrf     = CSRFProtect()
sess     = Session()
loginmgr = LoginManager()
# Создаём Limiter без storage_uri; зададим хранилище через конфиг ниже
limiter  = Limiter(key_func=get_remote_address, default_limits=["300 per day"])

# Настройки Flask-Login
loginmgr.login_view = "auth_bp.login"       # куда редиректить неаутентифицированных
loginmgr.session_protection = "strong"      # базовая защита от перехвата cookie

def ext_init(app):
    """
    Подключаем все расширения к приложению + Redis-бекенды для сессий и rate limits.
    """
    # 1. Flask-Session: если используем Redis для сессий
    if app.config.get("SESSION_TYPE") == "redis":
        url = app.config.get("SESSION_REDIS_URL")
        if url:
            # создаём объект Redis-клиента и сохраняем в конфиге
            app.config["SESSION_REDIS"] = redis.from_url(url)

    sess.init_app(app)

    # 2. Flask-Limiter: задаём URI хранилища через конфиг
    storage_uri = app.config.get("SESSION_REDIS_URL", "memory://")
    app.config["RATELIMIT_STORAGE_URI"] = storage_uri
    limiter.init_app(app)

    # 3. CSRF / Flask-Login
    csrf.init_app(app)
    loginmgr.init_app(app)


class DBUser(UserMixin):
    """Обёртка-псевдомодель для Flask-Login (без SQLAlchemy)."""
    def __init__(self, row: dict):
        self.id       = row["id"]
        self.username = row["username"]
        self.role     = row["role"]
        self._row     = row  # при желании сохранить всё

    @property
    def is_admin(self) -> bool:
        return self.role == "admin"

@loginmgr.user_loader
def load_user(user_id: str):
    """Каждый запрос → дотащить пользователя из БД по id."""
    conn = get_db_connection()
    with conn.cursor() as cur:
        cur.execute("SELECT * FROM users WHERE id=%s", (user_id,))
        row = cur.fetchone()
    conn.close()
    return DBUser(row) if row else None
