"""
ScholarPress - Research Publication Platform
A comprehensive platform for managing academic journals and research publications.
"""

from flask import Flask, flash, redirect, request
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from flask_mail import Mail
from flask_wtf.csrf import CSRFProtect, CSRFError
import os

db = SQLAlchemy()
login_manager = LoginManager()
mail = Mail()
csrf = CSRFProtect()


def create_app(config_name=None):
    """Application factory for creating the Flask app."""
    app = Flask(__name__, 
                template_folder='../templates',
                static_folder='../static')
    
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {
        'pool_pre_ping': True,
        'pool_recycle': 25
    }
    
    # Load configuration
    app.config.from_object('config.Config')
    
    # Initialize extensions
    db.init_app(app)
    login_manager.init_app(app)
    mail.init_app(app)
    csrf.init_app(app)
    
    login_manager.login_view = 'auth.login'
    login_manager.login_message_category = 'info'
    
    # Register blueprints
    from app.routes.main import main_bp
    from app.routes.auth import auth_bp
    from app.routes.admin import admin_bp
    from app.routes.editor import editor_bp
    from app.routes.submission import submission_bp
    from app.routes.contact import contact_bp
    from app.routes.articles import articles_bp
    
    app.register_blueprint(main_bp)
    app.register_blueprint(auth_bp, url_prefix='/auth')
    app.register_blueprint(admin_bp, url_prefix='/admin')
    app.register_blueprint(editor_bp, url_prefix='/editor')
    app.register_blueprint(submission_bp, url_prefix='/submit')
    app.register_blueprint(contact_bp, url_prefix='/contact')
    app.register_blueprint(articles_bp, url_prefix='/articles')
    
    # Create database tables
    with app.app_context():
        db.create_all()
        
        # Create default admin if not exists
        from app.models import User, SiteSettings
        admin = User.query.filter_by(email='admin@scholarpress.org').first()
        if not admin:
            admin = User(
                email='admin@scholarpress.org',
                username='admin',
                role='admin',
                is_active=True
            )
            admin.set_password('admin123')
            db.session.add(admin)
            db.session.commit()
        
        # Create default site settings if not exists
        settings = SiteSettings.query.first()
        if not settings:
            settings = SiteSettings(
                site_name='ScholarPress',
                site_tagline='Advancing Research, Connecting Scholars',
                site_description='ScholarPress is a leading platform for academic research publication, connecting researchers worldwide.',
                contact_email='contact@scholarpress.org',
                hero_title='Publish Your Research with ScholarPress',
                hero_subtitle='Join thousands of researchers sharing their discoveries with the world',
                about_title='About ScholarPress',
                about_content='ScholarPress is dedicated to advancing scientific knowledge by providing an open, accessible platform for researchers to publish and discover high-quality academic work.'
            )
            db.session.add(settings)
            db.session.commit()
    
    # Context processor to make settings available in all templates
    @app.context_processor
    def inject_settings():
        from app.models import SiteSettings
        from datetime import datetime
        settings = SiteSettings.query.first()
        return {
            'settings': settings,
            'site_settings': settings,
            'now': datetime.now
        }
    
    # Handle CSRF errors gracefully
    @app.errorhandler(CSRFError)
    def handle_csrf_error(e):
        flash('Your session has expired. Please try submitting again.', 'warning')
        return redirect(request.referrer or '/')
    
    return app
