import os
from flask import Flask, send_from_directory, request, redirect, url_for, flash
from .config import config
from .extensions import db, migrate, login_manager, mail, bcrypt, csrf, limiter #, celery_app, make_celery
from app.services import init_mail
from flask_wtf.csrf import CSRFError
import logging
from logging.handlers import RotatingFileHandler
from werkzeug.middleware.proxy_fix import ProxyFix
from app.services.rate_limit_service import bootstrap_default_limits_if_missing

def create_app(config_name=None):
    if config_name is None:
        config_name = os.getenv('FLASK_ENV', 'default')

    app = Flask(__name__, instance_relative_config=True)
    # Honrar cabeceras X-Forwarded-* cuando estamos detrás de un proxy (Apache/Nginx)
    # Esto es especialmente importante para obtener la IP real del cliente y que
    # el rate limiting por IP funcione correctamente.
    app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_port=1)
    app.config.from_object(config[config_name])
    config[config_name].init_app(app)

    # Crear la carpeta 'instance' si no existe, para SQLite y otros archivos
    try:
        os.makedirs(app.instance_path)
    except OSError:
        pass # La carpeta ya existe

    # Inicializar extensiones
    db.init_app(app)
    migrate.init_app(app, db)
    login_manager.init_app(app)
    mail.init_app(app)
    bcrypt.init_app(app)
    csrf.init_app(app)
    # Rate limiting
    limiter.init_app(app)
    
    # Inicializar servicios propios
    init_mail(app)

    # Configuración de logging
    if app.debug:
        # Configuración para el logger 'blog_logger'
        logger = logging.getLogger('debug_logger')
        logger.setLevel(logging.DEBUG)
        
        # Handler para la consola
        console_handler = logging.StreamHandler()
        console_handler.setLevel(logging.DEBUG)
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        console_handler.setFormatter(formatter)
        logger.addHandler(console_handler)

        app.logger.debug("Logging de debug activo")
    # global celery_app
    # celery_app = make_celery(app) # Descomentar si se usa Celery

    # Registrar Blueprints
    # Estas importaciones fallarán si los blueprints no existen aún.
    # Los comentaremos y los añadiremos a medida que creemos los blueprints.
    from .blueprints.public import public_bp
    app.register_blueprint(public_bp)

    from .blueprints.auth import auth_bp
    app.register_blueprint(auth_bp)

    from .blueprints.blog import blog_bp
    app.register_blueprint(blog_bp, url_prefix='/blog')

    from .blueprints.invoice import invoice_bp
    app.register_blueprint(invoice_bp, url_prefix='/facturas')

    from .blueprints.commercial_invoice import commercial_invoice_bp
    app.register_blueprint(commercial_invoice_bp, url_prefix='/facturas-comercial')

    from .blueprints.contact import bp as contact_bp
    app.register_blueprint(contact_bp)
    
    from .blueprints.api import api_bp
    app.register_blueprint(api_bp)
    
    from .blueprints.admin import admin_bp, init_app as init_admin_app
    app.register_blueprint(admin_bp)
    init_admin_app(app)  # Inicializa comandos CLI y otras configuraciones del admin
    
    # Manejador global para errores de CSRF (token inválido/ausente)
    @app.errorhandler(CSRFError)
    def handle_csrf_error(e):
        app.logger.warning(f"CSRF error: {e.description}")
        flash(f'Error de seguridad: token CSRF inválido o ausente. {e.description}', 'danger')
        return redirect(request.referrer or url_for('public.home'))

    # Manejador para rate limiting (429 Too Many Requests)
    @app.errorhandler(429)
    def handle_ratelimit_error(e):
        try:
            description = getattr(e, 'description', '')
        except Exception:
            description = ''
        app.logger.warning(f"Rate limit excedido: {description}")
        flash('Has excedido el número de intentos permitidos. Inténtalo de nuevo más tarde.', 'warning')
        return redirect(request.referrer or url_for('public.home'))
    
    # Modelos (importante para Flask-Migrate)
    # Esta importación es necesaria para que Flask-Migrate detecte los modelos
    from . import models

    # Context processors (si son necesarios)
    # @app.context_processor
    # def inject_global_vars():
    #     return dict(site_name="Olé Consulting")

    # Shell context for flask shell
    @app.shell_context_processor
    def make_shell_context():
        # Añade aquí los modelos y otras variables que quieras disponibles en `flask shell`
        # Por ahora, lo dejamos más simple hasta crear los modelos:
        return {'db': db}

    # Rutas de prueba o principales (opcional, mejor en blueprints)
    @app.route('/hello') # Ruta de prueba para verificar que la app funciona
    def hello():
        return 'Hello, World from Olé Consulting base app!'

    @app.route('/uploads/<path:filename>')
    def uploaded_file(filename):
        # Servir siempre desde la carpeta configurada en UPLOAD_FOLDER (e.g., app/static/uploads)
        directory = app.config['UPLOAD_FOLDER']
        app.logger.debug(f"Serving file {filename} from directory: {directory}")
        # Si la ruta contiene 'uploads/', eliminarla para evitar problemas
        if filename.startswith('uploads/'):
            filename = filename[8:]  # Quitar 'uploads/'
        return send_from_directory(directory, filename)

    # Inicializar claves de rate limiting por defecto si faltan
    # Comentado temporalmente para permitir la migración que crea la tabla settings
    # try:
    #     with app.app_context():
    #         bootstrap_default_limits_if_missing()
    # except Exception as e:
    #     app.logger.info(f"Rate limit bootstrap skipped: {e}")

    return app
