"""
app_init.py
===========
Flask application factory pattern.
"""

from flask import Flask, g, render_template
from flask_cors import CORS
from flask_session import Session
from werkzeug.middleware.proxy_fix import ProxyFix
from services_auth_service import AuthService
from routes_auth import auth_bp
import logging
import os
from datetime import datetime


def create_app(config=None):
    """Factory function per creare l'app Flask."""
    
    # Crea istanza Flask
    app = Flask(__name__, 
                template_folder='templates',
                static_folder='static')
    
    # ============================================================================
    # PROXY FIX - Necessario quando Flask è dietro a reverse proxy (Apache)
    # ============================================================================
    app.wsgi_app = ProxyFix(
        app.wsgi_app,
        x_for=1,          # X-Forwarded-For
        x_proto=1,        # X-Forwarded-Proto (http/https)
        x_host=1,         # X-Forwarded-Host
        x_prefix=1        # X-Script-Name (per il path prefix /enigma_inventario)
    )
    
    # Setup configurazione
    app.config['DEBUG'] = os.getenv('FLASK_DEBUG', 'False') == 'True'
    app.config['ENV'] = os.getenv('FLASK_ENV', 'production')
    app.config['SECRET_KEY'] = os.getenv('FLASK_SECRET_KEY', 'dev-secret-key')
    
    # Configurazione sessione Flask
    app.config['SESSION_TYPE'] = 'filesystem'
    app.config['SESSION_PERMANENT'] = False
    app.config['SESSION_FILE_DIR'] = '/tmp/enigma_sessions'
    
    # Inizializza sessione
    Session(app)
    
    # Configurazione CORS
    CORS(app, resources={r"/api/*": {"origins": "*"}})
    
    # Setup logging
    setup_logging(app)
    
    # Crea auth_service
    auth_service = _create_auth_service()
    
    @app.before_request
    def before_request():
        g.auth_service = auth_service
    
    # Registra blueprints
    app.register_blueprint(auth_bp)
    
    # Registra blueprint inventory
    from app.routes.inventory import inventory_bp
    app.register_blueprint(inventory_bp)
    
    # Registra routes di sistema
    register_system_routes(app)
    
    # Setup error handlers
    setup_error_handlers(app)
    
    # ============================================================================
    # ROUTES HTML - Frontend Pages
    # ============================================================================
    
    @app.route('/login')
    def login_page():
        return render_template('login.html')
    
    @app.route('/dashboard')
    def dashboard():
        return render_template('dashboard.html')
    
    @app.route('/inventory/scanner')
    def scanner():
        return render_template('scanner.html')
    
    # ============================================================================
    # ROUTE ALIAS - CompatibilitÃ  Frontend
    # ============================================================================
    # Le API REST sono su /api/v1/auth/* ma il frontend chiama /auth/*
    # Questi alias mantengono compatibilitÃ  senza duplicare codice
    
    @app.route('/auth/login', methods=['POST', 'GET'])
    def auth_login_alias():
        """Alias per /api/v1/auth/login - usato dal frontend"""
        from flask import request, jsonify, redirect, url_for
        
        if request.method == 'GET':
            # GET -> redirect alla login page
            return redirect(url_for('login_page'))
        
        # POST -> proxy al vero endpoint API
        auth_login_func = app.view_functions.get('auth.login')
        if auth_login_func:
            return auth_login_func()
        else:
            return jsonify({'error': 'Auth endpoint not found'}), 500
    
    @app.route('/auth/logout', methods=['POST'])
    def auth_logout_alias():
        """Alias per /api/v1/auth/logout"""
        auth_logout_func = app.view_functions.get('auth.logout')
        if auth_logout_func:
            return auth_logout_func()
        else:
            from flask import jsonify
            return jsonify({'error': 'Auth endpoint not found'}), 500
    
    @app.route('/auth/refresh-token', methods=['POST'])
    def auth_refresh_alias():
        """Alias per /api/v1/auth/refresh-token"""
        auth_refresh_func = app.view_functions.get('auth.refresh_token')
        if auth_refresh_func:
            return auth_refresh_func()
        else:
            from flask import jsonify
            return jsonify({'error': 'Auth endpoint not found'}), 500
    
    @app.route('/auth/me', methods=['GET'])
    def auth_me_alias():
        """Alias per /api/v1/auth/me"""
        auth_me_func = app.view_functions.get('auth.get_current_user')
        if auth_me_func:
            return auth_me_func()
        else:
            from flask import jsonify
            return jsonify({'error': 'Auth endpoint not found'}), 500
    
    app.logger.info("âœ… Flask app initialized")
    
    return app


def _create_auth_service():
    """Crea istanza AuthService."""
    db_config = {
        'host': os.getenv('DB_HOST', 'localhost'),
        'user': os.getenv('DB_USER', 'enigma_user'),
        'password': os.getenv('DB_PASSWORD', 'arcana2026'),
        'database': os.getenv('DB_NAME', 'enigma'),
    }
    
    jwt_secret = os.getenv('JWT_SECRET_KEY', 'EnigmaProject')
    jwt_expiration = int(os.getenv('JWT_EXPIRATION_HOURS', 24))
    
    return AuthService(
        db_config=db_config,
        jwt_secret=jwt_secret,
        jwt_algorithm='HS256',
        jwt_expiration_hours=jwt_expiration
    )


def register_system_routes(app):
    """Registra routes di sistema."""
    
    @app.route('/health', methods=['GET'])
    def health():
        """Health check endpoint"""
        import pymysql
        
        db_ok = "â�Œ"
        db_error = None
        
        try:
            conn = pymysql.connect(
                host=os.getenv('DB_HOST', 'localhost'),
                user=os.getenv('DB_USER', 'enigma_user'),
                password=os.getenv('DB_PASSWORD', 'arcana2026'),
                database=os.getenv('DB_NAME', 'enigma'),
                charset='utf8mb4',
            )
            conn.close()
            db_ok = "âœ…"
        except Exception as e:
            db_error = str(e)
        
        return {
            'status': 'ðŸŸ¢ ENIGMA running',
            'environment': app.config['ENV'],
            'database': db_ok,
            'database_error': db_error,
            'version': '0.1.0-demo',
            'timestamp': datetime.utcnow().isoformat()
        }
    
    @app.route('/', methods=['GET'])
    def index():
        """Root endpoint - redirect to login"""
        from flask import redirect, url_for
        return redirect(url_for('login_page'))


def setup_logging(app):
    """Setup logging per l'app."""
    log_level = os.getenv('LOG_LEVEL', 'INFO')
    
    formatter = logging.Formatter(
        '[%(asctime)s] %(levelname)s in %(module)s: %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S'
    )
    
    console_handler = logging.StreamHandler()
    console_handler.setLevel(log_level)
    console_handler.setFormatter(formatter)
    
    try:
        log_dir = '/var/log/enigma_inventario'
        if not os.path.exists(log_dir):
            os.makedirs(log_dir, exist_ok=True)
        
        file_handler = logging.FileHandler(f'{log_dir}/app.log')
        file_handler.setLevel(log_level)
        file_handler.setFormatter(formatter)
        app.logger.addHandler(file_handler)
    except Exception as e:
        print(f"Warning: Could not setup file logging: {e}")
    
    app.logger.addHandler(console_handler)
    app.logger.setLevel(log_level)


def setup_error_handlers(app):
    """Setup custom error handlers."""
    
    @app.errorhandler(404)
    def not_found(error):
        return {
            'error': 'Not found',
            'code': 'NOT_FOUND',
            'path': str(error)
        }, 404
    
    @app.errorhandler(405)
    def method_not_allowed(error):
        return {
            'error': 'Method not allowed',
            'code': 'METHOD_NOT_ALLOWED'
        }, 405
    
    @app.errorhandler(500)
    def internal_error(error):
        app.logger.error(f"Internal error: {error}")
        return {
            'error': 'Internal server error',
            'code': 'INTERNAL_ERROR'
        }, 500

