"""Phase A — Add Domain, Capability models + new FKs.

Adds:
- Domain model (code, name, description, sort_order)
- Capability model (domain FK, module_name, name, slug, icon, sort_order, description)
- FeatureCatalog.capability FK (nullable, alongside existing group FK)
- ModuleCatalog.domain FK (nullable)

Data migration: copy FeatureGroup rows → Capability.
"""

import django.db.models.deletion
import uuid

from django.db import migrations, models


def _seed_default_domains(apps, schema_editor):
    """Insert canonical Domain rows."""
    Domain = apps.get_model("platform_modules", "Domain")
    defaults = [
        ("platform", "Platform", "Infrastructure and cross-cutting platform services.", 10),
        ("commerce", "Commerce", "Sales, marketing, and customer-facing operations.", 20),
        ("business", "Business", "Back-office operations: accounting, HR, projects, etc.", 30),
    ]
    for code, name, description, sort_order in defaults:
        Domain.objects.get_or_create(
            code=code,
            defaults={
                "name": name,
                "description": description,
                "sort_order": sort_order,
            },
        )


def _migrate_featuregroup_to_capability(apps, schema_editor):
    """Copy all FeatureGroup rows → Capability.

    During Phase A we dual-write; FeatureGroup remains as a deprecated
    read-only proxy until Phase D.
    """
    FeatureGroup = apps.get_model("platform_modules", "FeatureGroup")
    Capability = apps.get_model("platform_modules", "Capability")
    Domain = apps.get_model("platform_modules", "Domain")

    # Best-effort domain assignment based on FeatureGroup name patterns.
    domain_map = {d.code: d for d in Domain.objects.all()}
    # Heuristic mapping: group names that suggest platform infrastructure
    platform_groups = {"platform_core", "integrations", "automation", "ai", "reports"}
    commerce_groups = {"crm", "chat", "marketing", "website"}

    for fg in FeatureGroup.objects.all():
        slug_lower = fg.slug.lower()
        if slug_lower in platform_groups:
            domain = domain_map.get("platform")
        elif slug_lower in commerce_groups:
            domain = domain_map.get("commerce")
        else:
            domain = domain_map.get("business")

        # Infer module_name from slug (best-effort heuristic).
        # Most FeatureGroups map 1:1 to a module name.
        module_name = slug_lower

        Capability.objects.get_or_create(
            slug=fg.slug,
            defaults={
                "domain": domain,
                "module_name": module_name,
                "name": fg.name,
                "icon": fg.icon,
                "sort_order": fg.sort_order,
                "description": fg.description,
            },
        )


def _reverse_migrate_capability(apps, schema_editor):
    """No-op reverse: we do not delete Capability rows during rollback."""
    pass


def _backfill_featurecatalog_capability(apps, schema_editor):
    """Point FeatureCatalog.capability at the matching Capability row.

    Uses the existing ``group`` FK to find the corresponding Capability.
    During Phase A, FeatureGroup and Capability slugs match 1:1.
    """
    FeatureCatalog = apps.get_model("platform_modules", "FeatureCatalog")
    FeatureGroup = apps.get_model("platform_modules", "FeatureGroup")
    Capability = apps.get_model("platform_modules", "Capability")

    # Build a map: FeatureGroup.slug → Capability
    fg_slug_to_cap = {}
    for fg in FeatureGroup.objects.all():
        try:
            cap = Capability.objects.get(slug=fg.slug)
            fg_slug_to_cap[fg.pk] = cap
        except Capability.DoesNotExist:
            pass

    # Backfill FeatureCatalog rows that have a group FK
    updated = 0
    for fc in FeatureCatalog.objects.filter(group__isnull=False).select_related("group"):
        cap = fg_slug_to_cap.get(fc.group_id)
        if cap is not None:
            fc.capability = cap
            fc.save(update_fields=["capability"])
            updated += 1

    # Also try matching by module_name fallback for rows without group
    for fc in FeatureCatalog.objects.filter(capability__isnull=True).iterator():
        cap = Capability.objects.filter(module_name=fc.module_name).first()
        if cap is not None:
            fc.capability = cap
            fc.save(update_fields=["capability"])
            updated += 1


def _backfill_modulecatalog_domain(apps, schema_editor):
    """Point ModuleCatalog.domain based on module_type."""
    ModuleCatalog = apps.get_model("platform_modules", "ModuleCatalog")
    Domain = apps.get_model("platform_modules", "Domain")

    domain_map = {d.code: d for d in Domain.objects.all()}

    # Map module_type → domain code
    type_to_domain = {
        "platform": "platform",
        "business": "business",
    }

    updated = 0
    for mc in ModuleCatalog.objects.filter(domain__isnull=True):
        domain_code = type_to_domain.get(mc.module_type, "business")
        domain = domain_map.get(domain_code)
        if domain is not None:
            mc.domain = domain
            mc.save(update_fields=["domain"])
            updated += 1


class Migration(migrations.Migration):
    dependencies = [
        ("platform_modules", "0014_tier_model"),
    ]

    operations = [
        # ── Domain model ──────────────────────────────────────────────────
        migrations.CreateModel(
            name="Domain",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                (
                    "public_id",
                    models.UUIDField(
                        db_index=True,
                        default=uuid.uuid4,
                        editable=False,
                        unique=True,
                        verbose_name="public id",
                    ),
                ),
                ("created_at", models.DateTimeField(auto_now_add=True, verbose_name="created at")),
                ("updated_at", models.DateTimeField(auto_now=True, verbose_name="updated at")),
                (
                    "code",
                    models.SlugField(
                        db_index=True,
                        help_text="Stable machine-readable code, e.g. 'platform', 'commerce', 'business'.",
                        max_length=40,
                        unique=True,
                        verbose_name="code",
                    ),
                ),
                ("name", models.CharField(max_length=120, verbose_name="name")),
                (
                    "description",
                    models.TextField(blank=True, default="", verbose_name="description"),
                ),
                (
                    "sort_order",
                    models.PositiveSmallIntegerField(
                        db_index=True,
                        default=0,
                        help_text="Controls display order; lower values appear first.",
                        verbose_name="sort order",
                    ),
                ),
            ],
            options={
                "verbose_name": "domain",
                "verbose_name_plural": "domains",
                "ordering": ("sort_order", "code"),
            },
        ),
        # ── Capability model ───────────────────────────────────────────────
        migrations.CreateModel(
            name="Capability",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                (
                    "public_id",
                    models.UUIDField(
                        db_index=True,
                        default=uuid.uuid4,
                        editable=False,
                        unique=True,
                        verbose_name="public id",
                    ),
                ),
                ("created_at", models.DateTimeField(auto_now_add=True, verbose_name="created at")),
                ("updated_at", models.DateTimeField(auto_now=True, verbose_name="updated at")),
                (
                    "module_name",
                    models.CharField(
                        blank=True,
                        db_index=True,
                        default="",
                        help_text="The module that provides this capability, e.g. 'crm'.",
                        max_length=80,
                        verbose_name="module name",
                    ),
                ),
                (
                    "name",
                    models.CharField(
                        db_index=True,
                        help_text="Unique capability name, e.g. 'CRM Sales' or 'Reports'.",
                        max_length=120,
                        unique=True,
                        verbose_name="name",
                    ),
                ),
                (
                    "slug",
                    models.SlugField(
                        db_index=True,
                        help_text="URL-friendly identifier, e.g. 'crm-sales' or 'reports'.",
                        max_length=120,
                        unique=True,
                        verbose_name="slug",
                    ),
                ),
                (
                    "icon",
                    models.CharField(
                        blank=True,
                        default="",
                        help_text="Optional icon identifier for UI rendering.",
                        max_length=60,
                        verbose_name="icon",
                    ),
                ),
                (
                    "sort_order",
                    models.PositiveSmallIntegerField(
                        db_index=True,
                        default=0,
                        help_text="Controls display order; lower values appear first.",
                        verbose_name="sort order",
                    ),
                ),
                (
                    "description",
                    models.TextField(blank=True, default="", verbose_name="description"),
                ),
                (
                    "domain",
                    models.ForeignKey(
                        blank=True,
                        help_text="Top-level domain this capability belongs to.",
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="capabilities",
                        to="platform_modules.Domain",
                        verbose_name="domain",
                    ),
                ),
            ],
            options={
                "verbose_name": "capability",
                "verbose_name_plural": "capabilities",
                "ordering": ("sort_order", "name"),
            },
        ),
        # ── FeatureCatalog.capability FK ──────────────────────────────────
        migrations.AddField(
            model_name="featurecatalog",
            name="capability",
            field=models.ForeignKey(
                blank=True,
                help_text="Capability grouping (Phase A — replaces group).",
                null=True,
                on_delete=django.db.models.deletion.SET_NULL,
                related_name="features",
                to="platform_modules.Capability",
                verbose_name="capability",
            ),
        ),
        # ── ModuleCatalog.domain FK ───────────────────────────────────────
        migrations.AddField(
            model_name="modulecatalog",
            name="domain",
            field=models.ForeignKey(
                blank=True,
                help_text="Top-level domain (Phase A — replaces module_type for grouping).",
                null=True,
                on_delete=django.db.models.deletion.SET_NULL,
                related_name="module_catalog_entries",
                to="platform_modules.Domain",
                verbose_name="domain",
            ),
        ),
        # ── Data migrations ────────────────────────────────────────────────
        migrations.RunPython(_seed_default_domains, migrations.RunPython.noop),
        migrations.RunPython(_migrate_featuregroup_to_capability, _reverse_migrate_capability),
        migrations.RunPython(_backfill_featurecatalog_capability, migrations.RunPython.noop),
        migrations.RunPython(_backfill_modulecatalog_domain, migrations.RunPython.noop),
    ]
