"""
DOOBAT - Bot Telegram Professionnel
Point d'entrée principal FastAPI
Copyright 2026 Vincent Gallet - Vincesoft
"""

import logging
import os
import sys
from contextlib import asynccontextmanager

import uvicorn
from fastapi import FastAPI, Request, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.trustedhost import TrustedHostMiddleware
from fastapi.responses import JSONResponse
from fastapi.staticfiles import StaticFiles
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.errors import RateLimitExceeded
from slowapi.util import get_remote_address

from routes.telegram_webhook import router as telegram_router
from services.cleanup_service import CleanupService
from services.security_service import SecurityService

# ── Configuration du logging ──────────────────────────────────────────────────

def setup_logging() -> logging.Logger:
    """Configure le système de logging centralisé."""
    from configparser import ConfigParser
    config = ConfigParser()
    config.read("config.ini")

    log_dir = config.get("LOGS", "log_dir", fallback="logs")
    log_level_str = config.get("LOGS", "log_level", fallback="INFO")
    max_bytes = config.getint("LOGS", "max_bytes", fallback=10_485_760)
    backup_count = config.getint("LOGS", "backup_count", fallback=5)

    os.makedirs(log_dir, exist_ok=True)

    log_level = getattr(logging, log_level_str.upper(), logging.INFO)

    formatter = logging.Formatter(
        fmt="%(asctime)s | %(levelname)-8s | %(name)-30s | %(message)s",
        datefmt="%Y-%m-%d %H:%M:%S",
    )

    # Handler fichier rotatif
    from logging.handlers import RotatingFileHandler
    file_handler = RotatingFileHandler(
        filename=os.path.join(log_dir, "doobat.log"),
        maxBytes=max_bytes,
        backupCount=backup_count,
        encoding="utf-8",
    )
    file_handler.setFormatter(formatter)
    file_handler.setLevel(log_level)

    # Handler console
    console_handler = logging.StreamHandler(sys.stdout)
    console_handler.setFormatter(formatter)
    console_handler.setLevel(log_level)

    root_logger = logging.getLogger()
    root_logger.setLevel(log_level)
    root_logger.addHandler(file_handler)
    root_logger.addHandler(console_handler)

    # Réduire le bruit des libs tierces
    logging.getLogger("httpx").setLevel(logging.WARNING)
    logging.getLogger("httpcore").setLevel(logging.WARNING)
    logging.getLogger("uvicorn.access").setLevel(logging.WARNING)

    return logging.getLogger("doobat.app")


logger = setup_logging()


# ── Lecture config ─────────────────────────────────────────────────────────────

def load_config():
    from configparser import ConfigParser
    config = ConfigParser()
    if not config.read("config.ini"):
        logger.critical("config.ini introuvable. Copier config.ini.example en config.ini.")
        sys.exit(1)
    return config


config = load_config()

# ── Rate limiter ───────────────────────────────────────────────────────────────

rate_limit_per_minute = config.getint("SECURITY", "rate_limit_per_minute", fallback=20)
limiter = Limiter(key_func=get_remote_address, default_limits=[f"{rate_limit_per_minute}/minute"])


# ── Lifespan (startup / shutdown) ─────────────────────────────────────────────

@asynccontextmanager
async def lifespan(app: FastAPI):
    """Initialisation et nettoyage au démarrage/arrêt."""
    logger.info("=" * 60)
    logger.info("DOOBAT Bot Telegram - Démarrage")
    logger.info("Copyright 2026 Vincent Gallet - Vincesoft")
    logger.info("=" * 60)

    # Créer les dossiers nécessaires
    for directory in ["pdf", "logs", "data", "static"]:
        os.makedirs(directory, exist_ok=True)

    # Initialiser le fichier de contacts Telegram si absent
    contacts_file = "data/telegram_contacts.json"
    if not os.path.exists(contacts_file):
        import json
        with open(contacts_file, "w", encoding="utf-8") as f:
            json.dump({}, f)
        logger.info("Fichier telegram_contacts.json initialisé.")

    # Lancer le nettoyage des anciens PDF au démarrage
    cleanup_service = CleanupService(config)
    cleaned = cleanup_service.cleanup_old_pdfs()
    logger.info(f"Nettoyage démarrage : {cleaned} PDF supprimé(s).")

    logger.info("DOOBAT prêt à recevoir des requêtes.")
    yield

    logger.info("DOOBAT - Arrêt propre.")


# ── Application FastAPI ────────────────────────────────────────────────────────

app = FastAPI(
    title="DOOBAT - Bot Telegram Professionnel",
    description="Bot Telegram connecté à Odoo pour commerciaux et clients",
    version="1.0.0",
    docs_url=None,   # Désactiver Swagger en production
    redoc_url=None,
    lifespan=lifespan,
)

# Attacher le limiter
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)

# ── Middlewares ────────────────────────────────────────────────────────────────

allowed_hosts_raw = config.get("SECURITY", "allowed_hosts", fallback="localhost")
allowed_hosts = [h.strip() for h in allowed_hosts_raw.split(",")]

app.add_middleware(
    TrustedHostMiddleware,
    allowed_hosts=allowed_hosts + ["*"],  # "*" pour compatibilité reverse proxy
)

app.add_middleware(
    CORSMiddleware,
    allow_origins=[config.get("SERVER", "base_url", fallback="https://doobat.doozen.fr")],
    allow_credentials=False,
    allow_methods=["POST", "GET"],
    allow_headers=["Content-Type", "X-Telegram-Bot-Api-Secret-Token"],
)

# Fichiers statiques
if os.path.exists("static"):
    app.mount("/static", StaticFiles(directory="static"), name="static")


# ── Routes ─────────────────────────────────────────────────────────────────────

app.include_router(telegram_router, prefix="/webhook", tags=["Telegram"])


# ── Endpoints système ──────────────────────────────────────────────────────────

@app.get("/health", tags=["Système"])
async def health_check():
    """Endpoint de santé pour monitoring."""
    return {
        "status": "ok",
        "service": "DOOBAT",
        "version": "1.0.0",
    }


@app.get("/", tags=["Système"])
async def root():
    """Racine - retourne info minimale."""
    return {"service": "DOOBAT Bot Telegram", "status": "running"}


# ── Gestionnaire d'erreurs global ──────────────────────────────────────────────

@app.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException):
    logger.warning(f"HTTP {exc.status_code} sur {request.url} : {exc.detail}")
    return JSONResponse(
        status_code=exc.status_code,
        content={"detail": exc.detail},
    )


@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
    logger.error(f"Erreur non gérée sur {request.url} : {exc}", exc_info=True)
    return JSONResponse(
        status_code=500,
        content={"detail": "Erreur interne du serveur."},
    )


# ── Lancement direct ───────────────────────────────────────────────────────────

if __name__ == "__main__":
    host = config.get("SERVER", "host", fallback="0.0.0.0")
    port = config.getint("SERVER", "port", fallback=8000)
    workers = config.getint("SERVER", "workers", fallback=1)

    logger.info(f"Lancement Uvicorn sur {host}:{port}")
    uvicorn.run(
        "app:app",
        host=host,
        port=port,
        workers=workers,
        log_level="warning",
        access_log=False,
        reload=False,
    )
