import os
import json
import importlib

from app.celery_instance import celery


def init_celery(app):
    """
    Wire up Celery to our Flask app, discover all plugin task modules
    and run any tasks_init hooks.
    """
    # 1. Configure broker & result backend from Flask config
    celery.conf.broker_url = app.config['CELERY_BROKER_URL']
    celery.conf.result_backend = app.config['CELERY_RESULT_BACKEND']

    # 2. Make all tasks run inside the Flask application context
    TaskBase = celery.Task

    class ContextTask(TaskBase):
        def __call__(self, *args, **kwargs):
            with app.app_context():
                return TaskBase.__call__(self, *args, **kwargs)

    celery.Task = ContextTask

    # 3. Discover all plugins by looking for plugin.json in plugins/
    plugins_dir = os.path.join(app.root_path, '..', 'plugins')
    task_modules = []

    for plugin_name in sorted(os.listdir(plugins_dir)):
        manifest = os.path.join(plugins_dir, plugin_name, 'plugin.json')
        if not os.path.isfile(manifest):
            continue

        # Load plugin metadata
        try:
            meta = json.load(open(manifest))
        except Exception:
            app.logger.error(f"[Celery] Failed to load plugin.json for '{plugin_name}'")
            continue

        # a) Gather task modules (string or dict or list)
        tasks_cfg = meta.get('tasks')
        if isinstance(tasks_cfg, str):
            task_modules.append(tasks_cfg)
        elif isinstance(tasks_cfg, dict) and tasks_cfg.get('module'):
            task_modules.append(tasks_cfg['module'])
        elif isinstance(tasks_cfg, list):
            for entry in tasks_cfg:
                if isinstance(entry, str):
                    task_modules.append(entry)
                elif isinstance(entry, dict) and entry.get('module'):
                    task_modules.append(entry['module'])

        # b) Run any tasks_init hooks (e.g. to register schedules)
        for hook in meta.get('tasks_init', []):
            module_name = hook.get('module')
            fn_name     = hook.get('callable')
            if not module_name or not fn_name:
                continue
            try:
                m  = importlib.import_module(module_name)
                fn = getattr(m, fn_name)
                # pass the Celery instance so they can register schedules, etc.
                fn(celery)
            except Exception as e:
                app.logger.error(f"[Celery] Failed tasks_init for '{plugin_name}': {e}")

    # 4. Autodiscover all gathered task modules
    if task_modules:
        celery.autodiscover_tasks(task_modules)
        app.logger.info(f"[Celery] Autodiscovered tasks in: {task_modules}")

    return celery


# Immediately bootstrap Celery whenever this module is imported
from app import create_app
_flask_app = create_app()
init_celery(_flask_app)
