"""`python manage.py provision_benchmark` — generate benchmark datasets.

Usage:
  python manage.py provision_benchmark --spec my_spec
  python manage.py provision_benchmark --tenant 1 --entity crm.Contact --count 10000
  python manage.py provision_benchmark --dry-run --spec my_spec
"""

from __future__ import annotations

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

from simorgh.apps.provisioning.benchmark import BenchmarkGenerator, BenchmarkSpec, EntitySpec


class Command(BaseCommand):
    help = "Generate benchmark datasets for performance and load testing."

    def add_arguments(self, parser):
        parser.add_argument(
            "--spec",
            dest="spec_module",
            default=None,
            help="Dotted path to a BenchmarkSpec instance (e.g., myapp.benchmarks.my_spec).",
        )
        parser.add_argument(
            "--tenant",
            dest="tenant_slug",
            default=None,
            help="Tenant slug to scope benchmark data to.",
        )
        parser.add_argument(
            "--entity",
            dest="entity_model",
            default=None,
            help="Quick mode: Django model label (e.g., crm.Contact).",
        )
        parser.add_argument(
            "--count",
            dest="count",
            type=int,
            default=1000,
            help="Quick mode: number of entities to create.",
        )
        parser.add_argument(
            "--seed",
            dest="seed",
            type=int,
            default=None,
            help="Random seed for reproducible generation.",
        )
        parser.add_argument(
            "--dry-run",
            action="store_true",
            default=False,
            help="Estimate without generating data.",
        )
        parser.add_argument(
            "--batch-size",
            dest="batch_size",
            type=int,
            default=500,
            help="Batch size for bulk_create.",
        )

    def handle(self, *args: object, **options: object) -> None:
        dry_run: bool = options["dry_run"]
        spec_module: str | None = options["spec_module"]
        tenant_slug: str | None = options["tenant_slug"]
        entity_model: str | None = options["entity_model"]
        count: int = options["count"]
        seed: int | None = options["seed"]
        batch_size: int = options["batch_size"]

        context: dict = {}

        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 spec_module:
            spec = self._load_spec(spec_module)
        elif entity_model:
            spec = BenchmarkSpec(
                name=f"quick_{entity_model.replace('.', '_')}",
                entities=[
                    EntitySpec(
                        model=entity_model,
                        count=count,
                        batch_size=batch_size,
                    )
                ],
                seed=seed,
            )
        else:
            raise CommandError("Provide either --spec or --entity + --count.")

        self.stdout.write(self.style.MIGRATE_HEADING(
            f"Benchmark: {spec.name}"
        ))
        if dry_run:
            self.stdout.write(f"  Total entities to generate: {spec.total_entities():,}")
            self.stdout.write(f"  Entity types: {len(spec.entities)}")
            if spec.tenant_count > 1:
                self.stdout.write(f"  Tenants: {spec.tenant_count}")
            self.stdout.write(self.style.NOTICE("\n  [dry-run] No data created."))
            return

        gen = BenchmarkGenerator(spec)

        def progress(current: int, total: int, entity: str) -> None:
            pct = current / total * 100
            self.stdout.write(f"  [{current:>6,}/{total:,}] {pct:5.1f}%  {entity}")

        report = gen.run(context=context, progress_callback=progress)

        self.stdout.write("")
        self.stdout.write(self.style.SUCCESS(report.summary()))

    def _load_spec(self, dotted_path: str) -> BenchmarkSpec:
        import importlib

        parts = dotted_path.rsplit(".", 1)
        if len(parts) != 2:
            raise CommandError(f"Invalid spec path: {dotted_path!r}")
        module_name, attr_name = parts
        try:
            mod = importlib.import_module(module_name)
        except ImportError as e:
            raise CommandError(f"Cannot import {module_name!r}: {e}") from e
        spec = getattr(mod, attr_name, None)
        if spec is None:
            raise CommandError(f"{dotted_path!r} not found.")
        if not isinstance(spec, BenchmarkSpec):
            raise CommandError(f"{dotted_path!r} is not a BenchmarkSpec instance.")
        return spec
