"""`python manage.py provision_seed` — execute provisioning fixtures via the engine.

Usage:
  python manage.py provision_seed
  python manage.py provision_seed --tenant momenin
  python manage.py provision_seed --workspace main-workspace
  python manage.py provision_seed --dry-run
  python manage.py provision_seed --names tenant_roles,demo_users
"""

from __future__ import annotations

from django.core.management.base import BaseCommand, CommandError

from simorgh.apps.provisioning.services import ProvisioningService


class Command(BaseCommand):
    help = "Execute registered provisioning fixtures via the Data Provisioning Engine."

    def add_arguments(self, parser):
        parser.add_argument(
            "--tenant",
            dest="tenant_slug",
            default=None,
            help="Run seed only for a specific tenant slug.",
        )
        parser.add_argument(
            "--workspace",
            dest="workspace_slug",
            default=None,
            help="Run seed only for a specific workspace slug.",
        )
        parser.add_argument(
            "--dry-run",
            action="store_true",
            default=False,
            help="Resolve dependencies and preview without executing.",
        )
        parser.add_argument(
            "--names",
            dest="names",
            default=None,
            help="Comma-separated list of fixture provider names to run (default: all).",
        )
        parser.add_argument(
            "--scope",
            dest="scope",
            default=None,
            choices=["global", "tenant", "workspace"],
            help="Filter providers by scope.",
        )
        parser.add_argument(
            "--tag",
            dest="tag",
            default=None,
            help="Filter providers by tag.",
        )

    def handle(self, *args: object, **options: object) -> None:
        dry_run: bool = options["dry_run"]
        tenant_slug: str | None = options["tenant_slug"]
        workspace_slug: str | None = options["workspace_slug"]
        names_str: str | None = options["names"]
        scope: str | None = options["scope"]
        tag: str | None = options["tag"]

        service = ProvisioningService()
        self._autodiscover_providers(service)

        names = [n.strip() for n in names_str.split(",") if n.strip()] if names_str else None

        providers = service.list_providers(tag=tag, scope=scope)
        if names:
            providers = [p for p in providers if p.name in names]
            not_found = [n for n in names if n not in {p.name for p in providers}]
            if not_found:
                raise CommandError(f"Providers not registered: {', '.join(not_found)}")

        if not providers:
            self.stdout.write(self.style.WARNING("No matching providers found."))
            return

        self.stdout.write(self.style.MIGRATE_HEADING(
            f"Provisioning Seed — {len(providers)} provider(s)"
        ))

        context: dict = {}
        tenant = None
        workspace = None

        if tenant_slug:
            from simorgh.apps.tenants.models import Tenant, TenantStatus

            tenant = Tenant.objects.filter(slug=tenant_slug, status=TenantStatus.ACTIVE).first()
            if tenant is None:
                raise CommandError(f"Active tenant {tenant_slug!r} not found.")
            context["tenant"] = tenant
            context["tenant_id"] = tenant.pk
            context["tenant_slug"] = tenant.slug

        if workspace_slug:
            from simorgh.apps.workspaces.models import Workspace

            workspace = Workspace.objects.filter(slug=workspace_slug).first()
            if workspace is None:
                raise CommandError(f"Workspace {workspace_slug!r} not found.")
            context["workspace"] = workspace
            context["workspace_id"] = workspace.pk
            context["workspace_slug"] = workspace.slug
            if tenant is None:
                context["tenant"] = workspace.tenant
                context["tenant_id"] = workspace.tenant_id
                context["tenant_slug"] = workspace.tenant.slug

        if dry_run:
            self.stdout.write("\n  [DRY RUN] Resolved execution order:")
            resolver = service.create_seed_runner(names=[p.name for p in providers])
            order = resolver._resolver.resolve_names()
            for i, name in enumerate(order, 1):
                p = service.get_provider(name)
                self.stdout.write(f"    {i}. {name}  (scope={p.scope}, deps={list(p.depends_on)})")
            return

        from simorgh.apps.provisioning.scopes import build_context, tenant_scope, workspace_scope

        if workspace is not None:
            with workspace_scope(workspace):
                context = build_context(
                    tenant=workspace.tenant,
                    workspace=workspace,
                )
                results = service.seed(
                    context=context,
                    names=[p.name for p in providers],
                )
        elif tenant is not None:
            with tenant_scope(tenant):
                context = build_context(tenant=tenant)
                results = service.seed(
                    context=context,
                    names=[p.name for p in providers],
                )
        else:
            results = service.seed(
                context=context,
                names=[p.name for p in providers],
            )

        self._print_results(results)

    def _print_results(self, results) -> None:
        self.stdout.write("")
        total_c = 0
        total_u = 0
        total_d = 0
        for r in results:
            self.stdout.write(
                self.style.SUCCESS(
                    f"  {r.provider_name}: +{r.created} created, "
                    f"~{r.updated} updated, -{r.deleted} deleted"
                )
            )
            total_c += r.created
            total_u += r.updated
            total_d += r.deleted
        self.stdout.write("")
        self.stdout.write(
            self.style.SUCCESS(
                f"Provisioning seed complete. "
                f"Total: +{total_c} created, ~{total_u} updated, -{total_d} deleted"
            )
        )

    def _autodiscover_providers(self, service: ProvisioningService) -> None:
        """Auto-discover providers registered via Django apps' provisioning modules."""
        from django.apps import apps as django_apps

        for app_config in django_apps.get_app_configs():
            module_name = f"{app_config.name}.provisioning"
            try:
                __import__(module_name)
            except ImportError:
                continue
