import random
from flask import Flask, send_from_directory, jsonify
from flask_migrate import Migrate
from dotenv import load_dotenv
import os
from models import User, SiteSettings
from flask_wtf.csrf import generate_csrf
from routes.room_files import room_files_bp
from routes.room_members import room_members_bp
from routes.trash import trash_bp
from routes.admin_api import admin_api
from tasks import cleanup_trash
import click
from utils import timeago
from extensions import db, login_manager, csrf
from utils.email_templates import create_default_templates
from datetime import datetime
from sqlalchemy import text
from utils.asset_utils import get_asset_version

# Load environment variables
load_dotenv()

def create_app():
    app = Flask(__name__)

    # Configure the database
    app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL', 'postgresql://postgres:1253@localhost:5432/docupulse')
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'your-secure-secret-key-here')
    app.config['UPLOAD_FOLDER'] = os.path.join(app.root_path, 'static', 'uploads')
    app.config['CSS_VERSION'] = os.getenv('CSS_VERSION', '1.0.3')  # Add CSS version for cache busting
    app.config['SERVER_NAME'] = os.getenv('SERVER_NAME', '127.0.0.1:5000')
    app.config['PREFERRED_URL_SCHEME'] = os.getenv('PREFERRED_URL_SCHEME', 'http')

    # Initialize extensions
    db.init_app(app)
    migrate = Migrate(app, db)
    login_manager.init_app(app)
    login_manager.login_view = 'auth.login'
    csrf.init_app(app)

    @app.context_processor
    def inject_csrf_token():
        return dict(csrf_token=generate_csrf())

    @app.context_processor
    def inject_config():
        site_settings = SiteSettings.query.first()
        if not site_settings:
            site_settings = SiteSettings()
            db.session.add(site_settings)
            db.session.commit()
        return dict(config=app.config, site_settings=site_settings)

    @app.context_processor
    def inject_unread_notifications():
        from flask_login import current_user
        from utils import get_unread_count
        if current_user.is_authenticated:
            unread_count = get_unread_count(current_user.id)
            return {'unread_notifications': unread_count}
        return {'unread_notifications': 0}

    @app.template_filter('asset_version')
    def asset_version_filter(filename):
        """Template filter to get version hash for static assets"""
        return get_asset_version(filename) or ''

    # User loader for Flask-Login
    @login_manager.user_loader
    def load_user(user_id):
        return User.query.get(int(user_id))

    # Health check endpoint
    @app.route('/health')
    def health_check():
        try:
            # Check database connection with a timeout
            db.session.execute(text('SELECT 1'))
            db.session.commit()
            
            return jsonify({
                'status': 'healthy',
                'database': 'connected',
                'timestamp': datetime.utcnow().isoformat()
            }), 200
        except Exception as e:
            app.logger.error(f"Health check failed: {str(e)}")
            return jsonify({
                'status': 'unhealthy',
                'error': str(e),
                'timestamp': datetime.utcnow().isoformat()
            }), 500

    # Initialize routes
    from routes import init_app
    init_app(app)
    app.register_blueprint(room_files_bp, url_prefix='/api/rooms')
    app.register_blueprint(room_members_bp, url_prefix='/api/rooms')
    app.register_blueprint(trash_bp, url_prefix='/api/trash')
    app.register_blueprint(admin_api, url_prefix='/api/admin')

    @app.cli.command("cleanup-trash")
    def cleanup_trash_command():
        """Clean up files that have been in trash for more than 30 days."""
        cleanup_trash()
        click.echo("Trash cleanup completed.")

    @app.cli.command("create-admin")
    def create_admin():
        """Create the default administrator user."""
        admin = User.query.filter_by(email='administrator@docupulse.com').first()
        if admin:
            click.echo("Admin user already exists.")
            return
        
        admin = User(
            username='administrator',
            email='administrator@docupulse.com',
            last_name='None',
            company='docupulse',
            is_admin=True,
            is_active=True
        )
        admin.set_password('changeme')
        db.session.add(admin)
        db.session.commit()
        click.echo("Default administrator user created successfully.")

    # Register custom filters
    app.jinja_env.filters['timeago'] = timeago

    # Create default email templates if they don't exist
    with app.app_context():
        try:
            # Ensure database tables exist
            db.create_all()
            create_default_templates()
        except Exception as e:
            print(f"Warning: Could not create default templates: {e}")

    return app

app = create_app()

@app.errorhandler(404)
def page_not_found(e):
    from flask import render_template
    return render_template('common/404.html'), 404

@app.errorhandler(403)
def forbidden(e):
    from flask import render_template
    return render_template('common/403.html'), 403

@app.errorhandler(401)
def unauthorized(e):
    from flask import render_template
    return render_template('common/401.html'), 401

@app.errorhandler(400)
def bad_request(e):
    from flask import render_template
    return render_template('common/400.html'), 400

@app.errorhandler(500)
def internal_server_error(e):
    from flask import render_template
    import traceback
    error_details = f"{str(e)}\n\n{traceback.format_exc()}"
    app.logger.error(f"500 error: {error_details}")
    return render_template('common/500.html', error=error_details), 500

@app.route('/uploads/profile_pics/<filename>')
def profile_pic(filename):
    return send_from_directory('/app/uploads/profile_pics', filename)

if __name__ == '__main__':
    app.run(debug=True) 