"""Site formation.goscubatours.com : dossiers de formation PADI Open Water.

`app`, en bas de ce fichier, est l'application chargée par Passenger
(passenger_wsgi.py) et par `flask --app app init-db`.
"""
import click
from flask import Flask, flash, redirect, request, url_for
from flask.cli import with_appcontext
from flask_login import LoginManager, current_user
from sqlalchemy.exc import OperationalError

from auth import auth_bp
from config import Config
from models import db, User
from training import training_bp

# Tables InnoDB en utf8mb4 même si la base cPanel a gardé le jeu de caractères du serveur :
# les déclarations PADI contiennent « œ », absent de latin1.
for _table in db.metadata.tables.values():
    _table.dialect_kwargs.update(mysql_engine='InnoDB', mysql_charset='utf8mb4',
                                 mysql_collate='utf8mb4_unicode_ci')

login_manager = LoginManager()
login_manager.login_view = 'auth.login'
login_manager.login_message = 'Connectez-vous pour accéder à cette page.'
login_manager.login_message_category = 'info'


@login_manager.user_loader
def load_user(user_id):
    return db.session.get(User, int(user_id))


@click.command('init-db')
@with_appcontext
def init_db_command():
    """Crée les tables manquantes, sans toucher aux données existantes."""
    db.create_all()
    click.echo('Tables créées.')


def create_app(overrides=None):
    app = Flask(__name__)
    app.config.from_object(Config)
    app.config.update(overrides or {})
    for key, var in (('SECRET_KEY', 'SECRET_KEY'), ('SQLALCHEMY_DATABASE_URI', 'DATABASE_URL')):
        if not app.config.get(key):
            raise RuntimeError(f"Variable d'environnement {var} manquante : voir .env.example.")

    db.init_app(app)
    login_manager.init_app(app)
    app.register_blueprint(auth_bp)
    app.register_blueprint(training_bp)
    app.cli.add_command(init_db_command)

    @app.route('/')
    def index():
        return redirect(url_for('training.dashboard' if current_user.is_authenticated else 'auth.login'))

    @app.context_processor
    def site_context():
        return {'site_name': app.config['SITE_NAME'], 'allow_registration': app.config['ALLOW_REGISTRATION']}

    @app.after_request
    def security_headers(response):
        response.headers.setdefault('X-Content-Type-Options', 'nosniff')
        response.headers.setdefault('X-Frame-Options', 'SAMEORIGIN')
        response.headers.setdefault('Referrer-Policy', 'same-origin')
        return response

    @app.errorhandler(413)
    def too_large(e):
        flash('Envoi trop volumineux : 10 Mo maximum par document.', 'error')
        args = request.view_args or {}
        if args.get('student_id') is not None:
            return redirect(url_for('training.student', student_id=args['student_id']) + '#documents')
        record_id = args.get('record_id')
        if record_id is None:
            return redirect(url_for('index'))
        return redirect(url_for('training.record', record_id=record_id, tab='documents'))

    with app.app_context():
        try:
            db.create_all()
        except OperationalError:
            # Base injoignable au démarrage : on le journalise sans bloquer le processus ;
            # les requêtes suivantes se reconnecteront (pool_pre_ping).
            app.logger.exception('Création des tables impossible au démarrage')
    return app


app = create_app()
