from __future__ import annotations

import logging

from django.core.management.base import BaseCommand

from simorgh.apps.modules.registry import list_modules
from simorgh.apps.modules.services import sync_features_to_db, sync_modules_to_db

logger = logging.getLogger(__name__)


class Command(BaseCommand):
    help = (
        "Sync in-memory module manifests to the Feature DB table and "
        "optionally install/enable modules for a tenant."
    )

    def add_arguments(self, parser):
        parser.add_argument(
            "--tenant",
            type=str,
            help="Tenant slug or pk to install all registered modules for.",
        )
        parser.add_argument(
            "--enable",
            action="store_true",
            default=False,
            help="Also enable all installed modules for the tenant (requires --tenant).",
        )

    def handle(self, *args, **options):
        modules = list_modules()
        self.stdout.write(f"Found {len(modules)} registered modules in the in-memory registry:")
        for m in modules:
            self.stdout.write(
                f"  {m.name} v{m.version} — "
                f"{len(m.features)} features, {len(m.permissions)} perms, "
                f"{len(m.events)} events, {len(m.feature_flags)} flags"
            )

        feat_count = sync_features_to_db()
        self.stdout.write(self.style.SUCCESS(f"Synced {feat_count} features to the FeatureCatalog table."))
        mod_count = sync_modules_to_db()
        self.stdout.write(self.style.SUCCESS(f"Synced {mod_count} modules to ModuleCatalog + ModuleFeature tables."))

        tenant_ref = options.get("tenant")
        if tenant_ref:
            self._install_modules_for_tenant(modules, tenant_ref, enable=options.get("enable", False))
        elif options.get("enable"):
            self.stdout.write(self.style.WARNING("--enable requires --tenant to be specified."))

    def _install_modules_for_tenant(self, modules, tenant_ref, *, enable: bool = False):
        from django.db import transaction

        from simorgh.apps.modules.models import ModuleStatus, TenantModule
        from simorgh.apps.modules.services import enable_module, install_module
        from simorgh.apps.tenants.models import Tenant

        try:
            if tenant_ref.isdigit():
                tenant = Tenant.objects.get(pk=int(tenant_ref))
            else:
                tenant = Tenant.objects.get(slug=tenant_ref)
        except Tenant.DoesNotExist:
            self.stdout.write(self.style.ERROR(f"Tenant {tenant_ref!r} not found."))
            return

        installed = []
        for manifest in modules:
            try:
                with transaction.atomic():
                    install_module(tenant, manifest.name)
                installed.append(manifest.name)
                self.stdout.write(f"  Installed {manifest.name}")
            except Exception as e:
                self.stdout.write(f"  Skipped {manifest.name}: {e}")

        self.stdout.write(
            self.style.SUCCESS(
                f"Installed {len(installed)}/{len(modules)} modules for tenant {tenant.slug}."
            )
        )

        if enable:
            enabled = []
            for manifest in modules:
                try:
                    row = TenantModule.objects.filter(tenant=tenant, name=manifest.name).first()
                    if row and row.status != ModuleStatus.ENABLED:
                        with transaction.atomic():
                            enable_module(tenant, manifest.name)
                        enabled.append(manifest.name)
                        self.stdout.write(f"  Enabled {manifest.name}")
                    elif row and row.status == ModuleStatus.ENABLED:
                        self.stdout.write(f"  Already enabled: {manifest.name}")
                except Exception as e:
                    self.stdout.write(self.style.WARNING(f"  Could not enable {manifest.name}: {e}"))

            self.stdout.write(
                self.style.SUCCESS(
                    f"Enabled {len(enabled)} module(s) for tenant {tenant.slug}."
                )
            )
