"""
app/__init__.py – Application Factory de Flask.
Inicializa extensiones y registra blueprints.
"""
import logging
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from flask_wtf.csrf import CSRFProtect
from flask_mail import Mail

from config import config_map

# Extensiones globales (sin app aún)
db            = SQLAlchemy()
login_manager = LoginManager()
csrf          = CSRFProtect()
mail          = Mail()


def create_app(env: str = 'default') -> Flask:
    app = Flask(__name__)
    app.config.from_object(config_map[env])

    # Inicializar extensiones
    db.init_app(app)
    login_manager.init_app(app)
    csrf.init_app(app)
    mail.init_app(app)

    # Flask-Login: redirigir no autenticados
    login_manager.login_view = 'auth.login'
    login_manager.login_message = 'Por favor inicia sesión para acceder.'
    login_manager.login_message_category = 'warning'

    # Registrar blueprints
    from app.routes.auth      import auth_bp
    from app.routes.dashboard import dashboard_bp
    from app.routes.usuarios  import usuarios_bp
    from app.routes.sistemas  import sistemas_bp
    from app.routes.relacion  import relacion_bp
    from app.routes.cambios   import cambios_bp
    from app.routes.reportes  import reportes_bp

    app.register_blueprint(auth_bp)
    app.register_blueprint(dashboard_bp)
    app.register_blueprint(usuarios_bp)
    app.register_blueprint(sistemas_bp)
    app.register_blueprint(relacion_bp)
    app.register_blueprint(cambios_bp)
    app.register_blueprint(reportes_bp)

    # Filtro Jinja2 para formato de fechas
    @app.template_filter('fecha_mx')
    def fecha_mx(value):
        if value is None:
            return '-'
        try:
            return value.strftime('%d/%m/%Y')
        except Exception:
            return str(value)

    # Páginas de error personalizadas
    @app.errorhandler(404)
    def page_not_found(e):
        from flask import render_template
        return render_template('errores/404.html'), 404

    @app.errorhandler(500)
    def internal_error(e):
        from flask import render_template
        db.session.rollback()
        return render_template('errores/500.html'), 500

    # Logging básico
    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s [%(levelname)s] %(name)s: %(message)s',
    )

    return app
