from __future__ import annotations
import os
import platform
from pathlib import Path

from flask import Flask
from flask_login import LoginManager
from flask_migrate import Migrate
from flask_socketio import SocketIO
from flask_wtf import CSRFProtect
from dotenv import load_dotenv

from config import Config
from backend.models.user import db, load_user
from backend.routes import register_routes
from backend.services.logger import setup_logging
from backend.services import watchdog_handler

# 텔레그램 서비스 (별도 모듈)에서 가져옴
from telegram_bot_service import run_polling as telegram_run_polling


# ─────────────────────────────────────────────────────────────
# .env 파일 로드 (환경변수 우선순위 보장)
# ─────────────────────────────────────────────────────────────
load_dotenv()

# ─────────────────────────────────────────────────────────────
# 템플릿/정적 경로를 파일 위치 기준으로 안전하게 설정
# structure: <project_root>/backend/templates, <project_root>/backend/static
# ─────────────────────────────────────────────────────────────
BASE_DIR = Path(__file__).resolve().parent
TEMPLATE_DIR = (BASE_DIR / "backend" / "templates").resolve()
STATIC_DIR   = (BASE_DIR / "backend" / "static").resolve()

# Flask 애플리케이션 생성
app = Flask(__name__, template_folder=str(TEMPLATE_DIR), static_folder=str(STATIC_DIR))
app.config.from_object(Config)

# 로그 설정
setup_logging(app)

# ─────────────────────────────────────────────────────────────
# CSRF 보호 + 템플릿에서 {{ csrf_token() }} 사용 가능하게 주입
# ─────────────────────────────────────────────────────────────
csrf = CSRFProtect()
csrf.init_app(app)


@app.context_processor
def inject_csrf():
    try:
        from flask_wtf.csrf import generate_csrf
        return dict(csrf_token=generate_csrf)
    except Exception:
        # Flask-WTF 미설치/에러 시에도 앱이 뜨도록 방어
        return dict(csrf_token=lambda: "")


# ─────────────────────────────────────────────────────────────
# SocketIO: Windows 기본 threading, Linux는 eventlet 설치 시 eventlet 사용
# 환경변수 SOCKETIO_ASYNC_MODE 로 강제 지정 가능 ("threading"/"eventlet"/"gevent"/"auto")
# ─────────────────────────────────────────────────────────────
async_mode = (app.config.get("SOCKETIO_ASYNC_MODE") or "threading").lower()
if async_mode == "auto":
    async_mode = "threading"

if async_mode == "eventlet":
    # Windows에선 eventlet 비권장, Linux에서만 시도
    if platform.system() != "Windows":
        try:
            import eventlet  # type: ignore
            eventlet.monkey_patch()
        except Exception:
            async_mode = "threading"  # 폴백
    else:
        async_mode = "threading"

socketio = SocketIO(app, cors_allowed_origins="*", async_mode=async_mode)

# watchdog에서 socketio 사용
watchdog_handler.socketio = socketio


# ─────────────────────────────────────────────────────────────
# DB / 마이그레이션
# ─────────────────────────────────────────────────────────────
app.logger.info("DB URI = %s", app.config.get("SQLALCHEMY_DATABASE_URI"))
db.init_app(app)
Migrate(app, db)

# (선택) 개발 편의용: 테이블 자동 부트스트랩
# 환경변수 AUTO_BOOTSTRAP_DB=true 일 때만 동작 (운영에서는 flask db upgrade 사용 권장)
if os.getenv("AUTO_BOOTSTRAP_DB", "false").lower() == "true":
    from sqlalchemy import inspect

    with app.app_context():
        insp = inspect(db.engine)
        if "user" not in insp.get_table_names():
            db.create_all()
            app.logger.info("DB bootstrap: created tables via create_all()")


# ─────────────────────────────────────────────────────────────
# Login
# ─────────────────────────────────────────────────────────────
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = "auth.login"


@login_manager.user_loader
def _load_user(user_id: str):
    return load_user(user_id)


# 라우트 등록 (Blueprints 등)
register_routes(app, socketio)


# ─────────────────────────────────────────────────────────────
# 텔레그램 봇 폴링 서비스 (중복 실행 방지 포함)
# ─────────────────────────────────────────────────────────────
_bot_polling_started = False  # 전역 플래그로 중복 방지


def start_telegram_bot_polling() -> None:
    """텔레그램 봇 폴링을 백그라운드 스레드로 시작 (한 번만 실행)"""
    import threading

    global _bot_polling_started

    if _bot_polling_started:
        app.logger.warning("🤖 텔레그램 봇 폴링은 이미 시작됨 - 중복 요청 무시")
        return

    _bot_polling_started = True

    def _runner():
        try:
            # telegram_bot_service.run_polling(app) 호출
            telegram_run_polling(app)
        except Exception as e:
            app.logger.error("텔레그램 봇 폴링 서비스 오류: %s", e)

    polling_thread = threading.Thread(target=_runner, daemon=True)
    polling_thread.start()
    app.logger.info("🤖 텔레그램 봇 폴링 스레드 생성됨 (중복 방지 플래그 적용)")


# ─────────────────────────────────────────────────────────────
# 텔레그램 봇 폴링 자동 시작
# Flask 앱이 초기화되면 자동으로 봇 폴링 시작
# ─────────────────────────────────────────────────────────────
start_telegram_bot_polling()


# ─────────────────────────────────────────────────────────────
# 엔트리포인트
# ─────────────────────────────────────────────────────────────
if __name__ == "__main__":
    host = os.getenv("FLASK_HOST", "0.0.0.0")
    port = int(os.getenv("FLASK_PORT", 5000))
    debug = os.getenv("FLASK_DEBUG", "true").lower() == "true"

    socketio.run(app, host=host, port=port, debug=debug, allow_unsafe_werkzeug=True, use_reloader=False)