"""
Wakelai Voice AI SaaS Platform
Main application factory
"""
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from flask_migrate import Migrate
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
from flask_cors import CORS
import logging
import os
from logging.handlers import RotatingFileHandler

# Initialize extensions
db = SQLAlchemy()
login_manager = LoginManager()
migrate = Migrate()
limiter = Limiter(key_func=get_remote_address)
cors = CORS()


def create_app(config_name='development'):
    """Application factory"""
    from config import get_config

    app = Flask(__name__)
    app.config.from_object(get_config(config_name))

    # Initialize extensions with app
    init_extensions(app)

    # Setup logging
    setup_logging(app)

    # Register blueprints
    register_blueprints(app)

    # Register error handlers
    register_error_handlers(app)

    # Register context processors
    register_context_processors(app)

    # Create database tables
    with app.app_context():
        db.create_all()

    return app


def init_extensions(app):
    """Initialize Flask extensions"""
    db.init_app(app)
    login_manager.init_app(app)
    migrate.init_app(app, db)
    limiter.init_app(app)
    cors.init_app(app, resources={r"/api/*": {"origins": "*"}})

    # Login manager configuration
    login_manager.login_view = 'auth.login'
    login_manager.login_message = 'Please log in to access this page.'
    login_manager.login_message_category = 'info'
    login_manager.session_protection = 'strong'


def setup_logging(app):
    """Setup application logging"""
    if not app.debug and not app.testing:
        log_dir = os.path.dirname(app.config['LOG_FILE'])
        if not os.path.exists(log_dir):
            os.makedirs(log_dir)

        file_handler = RotatingFileHandler(
            app.config['LOG_FILE'],
            maxBytes=10240000,
            backupCount=10
        )
        file_handler.setFormatter(logging.Formatter(
            '%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'
        ))
        file_handler.setLevel(getattr(logging, app.config['LOG_LEVEL']))

        app.logger.addHandler(file_handler)
        app.logger.setLevel(getattr(logging, app.config['LOG_LEVEL']))
        app.logger.info('Wakelai startup')


def register_blueprints(app):
    """Register application blueprints"""
    from app.routes.main import main_bp
    from app.routes.auth import auth_bp
    from app.routes.dashboard import dashboard_bp
    from app.routes.api import api_bp
    from app.routes.instances import instances_bp
    from app.routes.billing import billing_bp

    app.register_blueprint(main_bp)
    app.register_blueprint(auth_bp, url_prefix='/auth')
    app.register_blueprint(dashboard_bp, url_prefix='/dashboard')
    app.register_blueprint(api_bp, url_prefix='/api')
    app.register_blueprint(instances_bp, url_prefix='/instances')
    app.register_blueprint(billing_bp, url_prefix='/billing')


def register_error_handlers(app):
    """Register error handlers"""

    @app.errorhandler(400)
    def bad_request(error):
        from flask import jsonify
        return jsonify({'error': 'Bad Request', 'message': str(error)}), 400

    @app.errorhandler(401)
    def unauthorized(error):
        from flask import jsonify
        return jsonify({'error': 'Unauthorized', 'message': str(error)}), 401

    @app.errorhandler(403)
    def forbidden(error):
        from flask import jsonify
        return jsonify({'error': 'Forbidden', 'message': str(error)}), 403

    @app.errorhandler(404)
    def not_found(error):
        from flask import jsonify, render_template
        if '/api/' in str(error):
            return jsonify({'error': 'Not Found', 'message': str(error)}), 404
        return render_template('errors/404.html'), 404

    @app.errorhandler(500)
    def internal_error(error):
        from flask import jsonify, render_template
        app.logger.error(f'Server error: {error}')
        if '/api/' in str(error):
            return jsonify({'error': 'Internal Server Error', 'message': str(error)}), 500
        return render_template('errors/500.html'), 500


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

    @app.context_processor
    def utility_processor():
        """Make utility functions available in templates"""
        def format_datetime(value, format='medium'):
            if format == 'full':
                format = '%Y-%m-%d %H:%M:%S'
            elif format == 'medium':
                format = '%Y-%m-%d %H:%M'
            else:
                format = '%Y-%m-%d'
            return value.strftime(format) if value else ''

        def format_bytes(value):
            """Format bytes to human readable"""
            for unit in ['B', 'KB', 'MB', 'GB']:
                if value < 1024.0:
                    return f"{value:.2f} {unit}"
                value /= 1024.0
            return f"{value:.2f} TB"

        return dict(
            format_datetime=format_datetime,
            format_bytes=format_bytes,
            app_name=app.config.get('APP_NAME', 'Wakelai'),
            base_url=app.config.get('BASE_URL', 'http://localhost:4000')
        )
