"""
Flask application factory and initialization
"""
from flask import Flask, request, jsonify, render_template
import os
import logging
from logging.handlers import RotatingFileHandler
from config.config import get_config

def create_app(config_name=None):
    """Application factory pattern"""
    # Get the project root directory (parent of app directory)
    project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    template_dir = os.path.join(project_root, 'templates')
    static_dir = os.path.join(project_root, 'static')
    
    app = Flask(__name__, template_folder=template_dir, static_folder=static_dir)
    
    # Load configuration
    config_class = get_config(config_name)
    app.config.from_object(config_class)
    
    # Ensure required directories exist
    _ensure_directories()
    
    # Setup logging
    _setup_logging(app)
    
    # Register blueprints
    _register_blueprints(app)
    
    # Register template filters
    _register_template_filters(app)
    
    # Register error handlers
    _register_error_handlers(app)
    
    # Add context processors
    _register_context_processors(app)
    
    return app

def _ensure_directories():
    """Ensure required directories exist"""
    directories = [
        'data',
        'data/uploads',
        'data/backups',
        'logs',
        'ansible/inventory',
        'ansible/playbooks',
        'ansible/roles'
    ]
    
    for directory in directories:
        os.makedirs(directory, exist_ok=True)

def _setup_logging(app):
    """Setup application logging"""
    if not app.debug and not app.testing:
        # File logging for production
        if app.config.get('LOG_FILE'):
            if not os.path.exists('logs'):
                os.mkdir('logs')
            
            file_handler = RotatingFileHandler(
                app.config['LOG_FILE'],
                maxBytes=10240000,  # 10MB
                backupCount=10
            )
            file_handler.setFormatter(logging.Formatter(
                '%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'
            ))
            file_handler.setLevel(logging.INFO)
            app.logger.addHandler(file_handler)
        
        app.logger.setLevel(logging.INFO)
        app.logger.info('Enhanced monitoring server startup')

def _register_blueprints(app):
    """Register all blueprints"""
    
    # Import blueprints here to avoid circular imports
    from app.api.logs import logs_bp
    from app.api.ansible import ansible_bp
    from app.api.wmt import wmt_api_bp
    from app.web.main import main_bp
    from app.web.ansible import ansible_web_bp
    from app.web.wmt import wmt_web_bp

    app.register_blueprint(logs_bp)
    app.register_blueprint(ansible_bp)
    app.register_blueprint(wmt_api_bp)
    app.register_blueprint(main_bp)
    app.register_blueprint(ansible_web_bp)
    app.register_blueprint(wmt_web_bp)

    # Add compatibility routes for old clients
    @app.route('/logs', methods=['POST'])
    def compatibility_logs():
        """Compatibility endpoint for old prezenta clients"""
        from flask import request, redirect, url_for
        import re
        
        # Forward the request to the new API endpoint
        # Import inside function to avoid circular imports
        from app.api.logs import submit_log
        return submit_log()


def _register_template_filters(app):
    """Register custom Jinja2 template filters."""
    import calendar
    from datetime import datetime as _dt

    @app.template_filter('local_dt')
    def local_dt_filter(value, fmt='%Y-%m-%d %H:%M'):
        """Convert a naive UTC datetime to server local time and format it.
        Usage: {{ some_utc_datetime | local_dt }}
               {{ some_utc_datetime | local_dt('%Y-%m-%d %H:%M:%S') }}
        """
        if value is None:
            return None
        try:
            # calendar.timegm treats the timetuple as UTC → returns POSIX timestamp
            # datetime.fromtimestamp then converts to local time using the system timezone
            ts = calendar.timegm(value.timetuple())
            return _dt.fromtimestamp(ts).strftime(fmt)
        except Exception:
            return value.strftime(fmt)

def _register_error_handlers(app):
    """Register error handlers"""
    
    @app.errorhandler(400)
    def bad_request(error):
        if request.is_json:
            return jsonify({
                'error': 'Bad request',
                'message': 'The request could not be understood by the server'
            }), 400
        return render_template('errors/400.html'), 400
    
    @app.errorhandler(401)
    def unauthorized(error):
        if request.is_json:
            return jsonify({
                'error': 'Unauthorized',
                'message': 'Authentication required'
            }), 401
        return render_template('errors/401.html'), 401
    
    @app.errorhandler(403)
    def forbidden(error):
        if request.is_json:
            return jsonify({
                'error': 'Forbidden',
                'message': 'Insufficient permissions'
            }), 403
        return render_template('errors/403.html'), 403
    
    @app.errorhandler(404)
    def not_found(error):
        if request.is_json:
            return jsonify({
                'error': 'Not found',
                'message': 'The requested resource was not found'
            }), 404
        try:
            return render_template('errors/404.html'), 404
        except Exception as e:
            # Fallback if template cannot be loaded
            app.logger.error(f'Error loading 404 template: {e}')
            return '''
            <!DOCTYPE html>
            <html>
            <head><title>404 - Page Not Found</title></head>
            <body>
                <h1>404 - Page Not Found</h1>
                <p>The requested resource was not found.</p>
                <a href="/">← Back to Dashboard</a>
            </body>
            </html>
            ''', 404
    
    @app.errorhandler(500)
    def internal_error(error):
        app.logger.error(f'Internal server error: {error}')
        if request.is_json:
            return jsonify({
                'error': 'Internal server error',
                'message': 'An unexpected error occurred'
            }), 500
        try:
            return render_template('errors/500.html'), 500
        except Exception as e:
            app.logger.error(f'Error loading 500 template: {e}')
            return '''
            <!DOCTYPE html>
            <html>
            <head><title>500 - Internal Server Error</title></head>
            <body>
                <h1>500 - Internal Server Error</h1>
                <p>An unexpected error occurred.</p>
                <a href="/">← Back to Dashboard</a>
            </body>
            </html>
            ''', 500

def _register_context_processors(app):
    """Register template context processors"""

    @app.context_processor
    def inject_config():
        from app.models import WMTUpdateRequest
        from config.database_config import get_db
        try:
            with get_db().get_session() as session:
                pending_wmt_count = session.query(WMTUpdateRequest).filter_by(status='pending').count()
                unconfigured_count = session.query(WMTUpdateRequest).filter_by(status='to_be_configured').count()
        except Exception:
            pending_wmt_count = 0
            unconfigured_count = 0
        return {
            'app_name': 'Enhanced Server Monitoring',
            'app_version': '2.0.0',
            'pending_wmt_count': pending_wmt_count,
            'unconfigured_count': unconfigured_count,
        }