import os
import json
import importlib
from flask import current_app
from datetime import datetime

def register_plugins(app):
    project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
    plugins_dir = os.path.join(project_root, 'plugins')
    loaded = []

    app.logger.info("🔌 Discovering plugins…")
    for name in sorted(os.listdir(plugins_dir)):
        manifest = os.path.join(plugins_dir, name, 'plugin.json')
        if not os.path.isfile(manifest):
            continue

        errors = []
        try:
            meta = json.load(open(manifest))
        except Exception as e:
            app.logger.error(f"  ✖ manifest load error for '{name}': {e}")
            continue

        info = {'name': name, 'models': [], 'routes': None, 'cli': [],
                'template_globals': [], 'subplugins': []}

        # 1) models
        for model_path in meta.get('models', []):
            try:
                importlib.import_module(model_path)
                info['models'].append(model_path)
            except Exception as e:
                errors.append(f"model '{model_path}': {e}")

        # 2) user_loader
        ul = meta.get('user_loader')
        if ul:
            try:
                m = importlib.import_module(ul['module'])
                fn = getattr(m, ul['callable'])
                fn(app.login_manager)
            except Exception as e:
                errors.append(f"user_loader '{ul}': {e}")

        # 3) routes
        rt = meta.get('routes')
        if rt:
            try:
                m      = importlib.import_module(rt['module'])
                bp_obj = getattr(m, rt['blueprint'])
                app.register_blueprint(bp_obj, url_prefix=rt.get('url_prefix'), strict_slashes=False)
                info['routes'] = f"{rt['module']}::{rt['blueprint']}"
            except Exception as e:
                errors.append(f"routes '{rt}': {e}")

        # 4) CLI
        raw_cli = meta.get('cli')
        if raw_cli:
            # wrap a single dict into a list so we can iterate uniformly
            cli_entries = raw_cli if isinstance(raw_cli, list) else [raw_cli]
            for cli_entry in cli_entries:
                try:
                    module_path   = cli_entry.get('module')
                    callable_name = cli_entry.get('callable')
                    m  = importlib.import_module(module_path)
                    fn = getattr(m, callable_name)
                    app.cli.add_command(fn)
                    info['cli'].append(f"{module_path}::{callable_name}")
                except Exception as e:
                    errors.append(f"cli '{cli_entry}': {e}")

        # 5) template_globals
        for tg in meta.get('template_globals', []):
            try:
                mod_name, fn_name = tg['callable'].rsplit('.', 1)
                m = importlib.import_module(mod_name)
                fn = getattr(m, fn_name)
                app.jinja_env.globals[tg['name']] = fn
                info['template_globals'].append(tg['name'])
            except Exception as e:
                errors.append(f"template_global '{tg}': {e}")

        # 6) subplugins
        for sp in meta.get('subplugins', []):
            sub = {'name': sp['name'], 'models': [], 'routes': None}
            for mp in sp.get('models', []):
                try:
                    importlib.import_module(mp)
                    sub['models'].append(mp)
                except Exception as e:
                    errors.append(f"subplugin model '{mp}': {e}")
            srt = sp.get('routes')
            if srt:
                try:
                    m      = importlib.import_module(srt['module'])
                    bp_obj = getattr(m, srt['blueprint'])
                    app.register_blueprint(bp_obj, url_prefix=srt.get('url_prefix'), strict_slashes=False)
                    sub['routes'] = f"{srt['module']}::{srt['blueprint']}"
                except Exception as e:
                    errors.append(f"subplugin routes '{srt}': {e}")
            info['subplugins'].append(sub)

        # Report
        if errors:
            app.logger.error(f"  ✖ Plugin '{name}' errors: " + "; ".join(errors))
        else:
            app.logger.info(f"  ✔ Plugin '{name}' loaded")
            loaded.append(info)

    # summary
    app.logger.info("🌟 Loaded plugins summary:")
    for p in loaded:
        app.logger.info(
            f"  • {p['name']}: models={p['models']}, routes={p['routes']}, "
            f"cli={p['cli']}, template_globals={p['template_globals']}, "
            f"subplugins={[s['name'] for s in p['subplugins']]}"
        )
