# Generated by Django 5.2 on 2026-01-09 17:14

import api.models
import django.core.validators
import django.db.models.deletion
import uuid
from decimal import Decimal
from django.db import migrations, models


def seed_intelligence_tiers(apps, schema_editor):
    IntelligenceTier = apps.get_model("api", "IntelligenceTier")
    PersistentLLMTier = apps.get_model("api", "PersistentLLMTier")
    ProfilePersistentTier = apps.get_model("api", "ProfilePersistentTier")
    BrowserLLMTier = apps.get_model("api", "BrowserLLMTier")
    ProfileBrowserTier = apps.get_model("api", "ProfileBrowserTier")
    PersistentAgent = apps.get_model("api", "PersistentAgent")

    tier_specs = [
        ("standard", "Standard", 0, Decimal("1.00")),
        ("premium", "Premium", 1, Decimal("2.00")),
        ("max", "Max", 2, Decimal("5.00")),
        ("ultra", "Ultra", 3, Decimal("20.00")),
        ("ultra_max", "Ultra Max", 4, Decimal("50.00")),
    ]

    multipliers = {key: default for key, _label, _rank, default in tier_specs}
    all_tiers_with_multipliers = list(
        PersistentLLMTier.objects.all().only("is_max", "is_premium", "credit_multiplier")
    )
    all_tiers_with_multipliers.extend(
        list(ProfilePersistentTier.objects.all().only("is_max", "is_premium", "credit_multiplier"))
    )
    for tier in all_tiers_with_multipliers:
        tier_key = "max" if tier.is_max else ("premium" if tier.is_premium else "standard")
        try:
            multiplier = Decimal(str(tier.credit_multiplier))
        except Exception:
            continue
        current = multipliers.get(tier_key)
        if current is None or multiplier > current:
            multipliers[tier_key] = multiplier

    for key, display_name, rank, default_multiplier in tier_specs:
        IntelligenceTier.objects.update_or_create(
            key=key,
            defaults={
                "display_name": display_name,
                "rank": rank,
                "credit_multiplier": multipliers.get(key, default_multiplier),
            },
        )

    tier_map = {tier.key: tier for tier in IntelligenceTier.objects.all()}
    standard_id = tier_map["standard"].id
    premium_id = tier_map["premium"].id
    max_id = tier_map["max"].id

    PersistentLLMTier.objects.filter(is_max=True).update(intelligence_tier_id=max_id)
    PersistentLLMTier.objects.filter(is_premium=True, is_max=False).update(intelligence_tier_id=premium_id)
    PersistentLLMTier.objects.filter(is_premium=False, is_max=False).update(intelligence_tier_id=standard_id)

    ProfilePersistentTier.objects.filter(is_max=True).update(intelligence_tier_id=max_id)
    ProfilePersistentTier.objects.filter(is_premium=True, is_max=False).update(intelligence_tier_id=premium_id)
    ProfilePersistentTier.objects.filter(is_premium=False, is_max=False).update(intelligence_tier_id=standard_id)

    BrowserLLMTier.objects.filter(is_premium=True).update(intelligence_tier_id=premium_id)
    BrowserLLMTier.objects.filter(is_premium=False).update(intelligence_tier_id=standard_id)

    ProfileBrowserTier.objects.filter(is_premium=True).update(intelligence_tier_id=premium_id)
    ProfileBrowserTier.objects.filter(is_premium=False).update(intelligence_tier_id=standard_id)

    PersistentAgent.objects.filter(preferred_llm_tier_value="ultra_max").update(
        preferred_llm_tier_id=tier_map["ultra_max"].id
    )
    PersistentAgent.objects.filter(preferred_llm_tier_value="ultra").update(
        preferred_llm_tier_id=tier_map["ultra"].id
    )
    PersistentAgent.objects.filter(preferred_llm_tier_value="max").update(preferred_llm_tier_id=max_id)
    PersistentAgent.objects.filter(preferred_llm_tier_value="premium").update(preferred_llm_tier_id=premium_id)
    PersistentAgent.objects.filter(preferred_llm_tier_value="standard").update(preferred_llm_tier_id=standard_id)
    PersistentAgent.objects.filter(preferred_llm_tier__isnull=True).update(preferred_llm_tier_id=standard_id)


def collapse_intelligence_tiers_for_rollback(apps, schema_editor):
    PersistentLLMTier = apps.get_model("api", "PersistentLLMTier")
    ProfilePersistentTier = apps.get_model("api", "ProfilePersistentTier")
    BrowserLLMTier = apps.get_model("api", "BrowserLLMTier")
    ProfileBrowserTier = apps.get_model("api", "ProfileBrowserTier")
    PersistentAgent = apps.get_model("api", "PersistentAgent")

    def has_field(model, name: str) -> bool:
        return any(field.name == name for field in model._meta.fields)

    def legacy_flags_for_tier(tier) -> tuple[bool, bool]:
        key = getattr(getattr(tier, "intelligence_tier", None), "key", "standard")
        if key == "premium":
            return True, False
        if key in ("max", "ultra", "ultra_max"):
            return False, True
        return False, False

    def legacy_browser_flag(tier) -> bool:
        key = getattr(getattr(tier, "intelligence_tier", None), "key", "standard")
        return key != "standard"

    def resequence_tiers(tiers, group_key_fn, update_fields):
        grouped = {}
        for tier in tiers:
            grouped.setdefault(group_key_fn(tier), []).append(tier)
        for group in grouped.values():
            for index, tier in enumerate(group, start=1):
                tier.order = index
        if tiers:
            model = tiers[0].__class__
            model.objects.bulk_update(tiers, update_fields)

    persistent_tiers = list(
        PersistentLLMTier.objects.select_related("intelligence_tier").order_by(
            "token_range_id",
            "intelligence_tier__rank",
            "order",
            "id",
        )
    )
    for tier in persistent_tiers:
        is_premium, is_max = legacy_flags_for_tier(tier)
        tier.is_premium = is_premium
        tier.is_max = is_max
        if has_field(PersistentLLMTier, "credit_multiplier") and getattr(tier, "intelligence_tier", None):
            tier.credit_multiplier = tier.intelligence_tier.credit_multiplier
    persistent_update_fields = ["is_premium", "is_max", "order"]
    if has_field(PersistentLLMTier, "credit_multiplier"):
        persistent_update_fields.append("credit_multiplier")
    resequence_tiers(
        persistent_tiers,
        lambda tier: (tier.token_range_id, tier.is_premium, tier.is_max),
        persistent_update_fields,
    )

    profile_persistent_tiers = list(
        ProfilePersistentTier.objects.select_related("intelligence_tier").order_by(
            "token_range_id",
            "intelligence_tier__rank",
            "order",
            "id",
        )
    )
    for tier in profile_persistent_tiers:
        is_premium, is_max = legacy_flags_for_tier(tier)
        tier.is_premium = is_premium
        tier.is_max = is_max
        if has_field(ProfilePersistentTier, "credit_multiplier") and getattr(tier, "intelligence_tier", None):
            tier.credit_multiplier = tier.intelligence_tier.credit_multiplier
    profile_persistent_update_fields = ["is_premium", "is_max", "order"]
    if has_field(ProfilePersistentTier, "credit_multiplier"):
        profile_persistent_update_fields.append("credit_multiplier")
    resequence_tiers(
        profile_persistent_tiers,
        lambda tier: (tier.token_range_id, tier.is_premium, tier.is_max),
        profile_persistent_update_fields,
    )

    browser_tiers = list(
        BrowserLLMTier.objects.select_related("intelligence_tier").order_by(
            "policy_id",
            "intelligence_tier__rank",
            "order",
            "id",
        )
    )
    for tier in browser_tiers:
        tier.is_premium = legacy_browser_flag(tier)
    resequence_tiers(
        browser_tiers,
        lambda tier: (tier.policy_id, tier.is_premium),
        ["is_premium", "order"],
    )

    profile_browser_tiers = list(
        ProfileBrowserTier.objects.select_related("intelligence_tier").order_by(
            "profile_id",
            "intelligence_tier__rank",
            "order",
            "id",
        )
    )
    for tier in profile_browser_tiers:
        tier.is_premium = legacy_browser_flag(tier)
    resequence_tiers(
        profile_browser_tiers,
        lambda tier: (tier.profile_id, tier.is_premium),
        ["is_premium", "order"],
    )

    if has_field(PersistentAgent, "preferred_llm_tier_value"):
        agents = list(PersistentAgent.objects.select_related("preferred_llm_tier"))
        for agent in agents:
            key = getattr(getattr(agent, "preferred_llm_tier", None), "key", "standard")
            if key in ("ultra", "ultra_max"):
                key = "max"
            if key not in ("standard", "premium", "max"):
                key = "standard"
            agent.preferred_llm_tier_value = key
        if agents:
            PersistentAgent.objects.bulk_update(agents, ["preferred_llm_tier_value"])


class Migration(migrations.Migration):

    dependencies = [
        ("api", "0256_persistentagentcompletion_response_metadata"),
    ]

    operations = [
        migrations.CreateModel(
            name="IntelligenceTier",
            fields=[
                ("id", models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
                ("key", models.SlugField(max_length=32, unique=True)),
                ("display_name", models.CharField(max_length=64)),
                (
                    "rank",
                    models.PositiveSmallIntegerField(
                        help_text="Higher rank means higher intelligence tier.",
                        unique=True,
                    ),
                ),
                (
                    "credit_multiplier",
                    models.DecimalField(
                        decimal_places=2,
                        default=Decimal("1.00"),
                        help_text="Multiplier applied to credit consumption for this intelligence tier.",
                        max_digits=6,
                        validators=[django.core.validators.MinValueValidator(Decimal("0.01"))],
                    ),
                ),
                ("created_at", models.DateTimeField(auto_now_add=True)),
                ("updated_at", models.DateTimeField(auto_now=True)),
            ],
            options={
                "ordering": ["rank", "key"],
            },
        ),
        migrations.AddField(
            model_name="promptconfig",
            name="ultra_enabled_tool_limit",
            field=models.PositiveSmallIntegerField(
                default=40,
                help_text="Number of concurrently enabled tools allowed for ultra tier agents.",
                validators=[django.core.validators.MinValueValidator(1)],
            ),
        ),
        migrations.AddField(
            model_name="promptconfig",
            name="ultra_max_enabled_tool_limit",
            field=models.PositiveSmallIntegerField(
                default=40,
                help_text="Number of concurrently enabled tools allowed for ultra max tier agents.",
                validators=[django.core.validators.MinValueValidator(1)],
            ),
        ),
        migrations.AddField(
            model_name="promptconfig",
            name="ultra_max_message_history_limit",
            field=models.PositiveSmallIntegerField(
                default=20,
                help_text="Number of recent messages included for ultra max tier agents.",
                validators=[django.core.validators.MinValueValidator(1)],
            ),
        ),
        migrations.AddField(
            model_name="promptconfig",
            name="ultra_max_prompt_token_budget",
            field=models.PositiveIntegerField(
                default=120000,
                help_text="Token budget applied when rendering prompts for ultra max tier agents.",
                validators=[django.core.validators.MinValueValidator(1)],
            ),
        ),
        migrations.AddField(
            model_name="promptconfig",
            name="ultra_max_tool_call_history_limit",
            field=models.PositiveSmallIntegerField(
                default=60,
                help_text="Number of recent tool calls included for ultra max tier agents.",
                validators=[django.core.validators.MinValueValidator(1)],
            ),
        ),
        migrations.AddField(
            model_name="promptconfig",
            name="ultra_max_unified_history_hysteresis",
            field=models.PositiveIntegerField(
                default=20,
                help_text="Unified history hysteresis for ultra max tier agents.",
                validators=[django.core.validators.MinValueValidator(1)],
            ),
        ),
        migrations.AddField(
            model_name="promptconfig",
            name="ultra_max_unified_history_limit",
            field=models.PositiveIntegerField(
                default=120,
                help_text="Unified history event limit for ultra max tier agents.",
                validators=[django.core.validators.MinValueValidator(1)],
            ),
        ),
        migrations.AddField(
            model_name="promptconfig",
            name="ultra_message_history_limit",
            field=models.PositiveSmallIntegerField(
                default=20,
                help_text="Number of recent messages included for ultra tier agents.",
                validators=[django.core.validators.MinValueValidator(1)],
            ),
        ),
        migrations.AddField(
            model_name="promptconfig",
            name="ultra_prompt_token_budget",
            field=models.PositiveIntegerField(
                default=120000,
                help_text="Token budget applied when rendering prompts for ultra tier agents.",
                validators=[django.core.validators.MinValueValidator(1)],
            ),
        ),
        migrations.AddField(
            model_name="promptconfig",
            name="ultra_tool_call_history_limit",
            field=models.PositiveSmallIntegerField(
                default=60,
                help_text="Number of recent tool calls included for ultra tier agents.",
                validators=[django.core.validators.MinValueValidator(1)],
            ),
        ),
        migrations.AddField(
            model_name="promptconfig",
            name="ultra_unified_history_hysteresis",
            field=models.PositiveIntegerField(
                default=20,
                help_text="Unified history hysteresis for ultra tier agents.",
                validators=[django.core.validators.MinValueValidator(1)],
            ),
        ),
        migrations.AddField(
            model_name="promptconfig",
            name="ultra_unified_history_limit",
            field=models.PositiveIntegerField(
                default=120,
                help_text="Unified history event limit for ultra tier agents.",
                validators=[django.core.validators.MinValueValidator(1)],
            ),
        ),
        migrations.AddField(
            model_name="browserllmtier",
            name="intelligence_tier",
            field=models.ForeignKey(
                null=True,
                on_delete=django.db.models.deletion.PROTECT,
                related_name="browser_tiers",
                to="api.intelligencetier",
            ),
        ),
        migrations.AddField(
            model_name="persistentllmtier",
            name="intelligence_tier",
            field=models.ForeignKey(
                null=True,
                on_delete=django.db.models.deletion.PROTECT,
                related_name="persistent_tiers",
                to="api.intelligencetier",
            ),
        ),
        migrations.AddField(
            model_name="profilebrowsertier",
            name="intelligence_tier",
            field=models.ForeignKey(
                null=True,
                on_delete=django.db.models.deletion.PROTECT,
                related_name="profile_browser_tiers",
                to="api.intelligencetier",
            ),
        ),
        migrations.AddField(
            model_name="profilepersistenttier",
            name="intelligence_tier",
            field=models.ForeignKey(
                null=True,
                on_delete=django.db.models.deletion.PROTECT,
                related_name="profile_persistent_tiers",
                to="api.intelligencetier",
            ),
        ),
        migrations.RenameField(
            model_name="persistentagent",
            old_name="preferred_llm_tier",
            new_name="preferred_llm_tier_value",
        ),
        migrations.AddField(
            model_name="persistentagent",
            name="preferred_llm_tier",
            field=models.ForeignKey(
                null=True,
                help_text="Preferred intelligence tier controlling LLM routing for this agent.",
                on_delete=django.db.models.deletion.PROTECT,
                related_name="preferred_by_agents",
                to="api.intelligencetier",
            ),
        ),
        migrations.RunPython(seed_intelligence_tiers, migrations.RunPython.noop),
        migrations.AlterField(
            model_name="browserllmtier",
            name="intelligence_tier",
            field=models.ForeignKey(
                default=api.models._get_default_intelligence_tier_id,
                on_delete=django.db.models.deletion.PROTECT,
                related_name="browser_tiers",
                to="api.intelligencetier",
            ),
        ),
        migrations.AlterField(
            model_name="persistentllmtier",
            name="intelligence_tier",
            field=models.ForeignKey(
                default=api.models._get_default_intelligence_tier_id,
                on_delete=django.db.models.deletion.PROTECT,
                related_name="persistent_tiers",
                to="api.intelligencetier",
            ),
        ),
        migrations.AlterField(
            model_name="profilebrowsertier",
            name="intelligence_tier",
            field=models.ForeignKey(
                default=api.models._get_default_intelligence_tier_id,
                on_delete=django.db.models.deletion.PROTECT,
                related_name="profile_browser_tiers",
                to="api.intelligencetier",
            ),
        ),
        migrations.AlterField(
            model_name="profilepersistenttier",
            name="intelligence_tier",
            field=models.ForeignKey(
                default=api.models._get_default_intelligence_tier_id,
                on_delete=django.db.models.deletion.PROTECT,
                related_name="profile_persistent_tiers",
                to="api.intelligencetier",
            ),
        ),
        migrations.AlterField(
            model_name="persistentagent",
            name="preferred_llm_tier",
            field=models.ForeignKey(
                default=api.models._get_default_intelligence_tier_id,
                help_text="Preferred intelligence tier controlling LLM routing for this agent.",
                on_delete=django.db.models.deletion.PROTECT,
                related_name="preferred_by_agents",
                to="api.intelligencetier",
            ),
        ),
        migrations.RemoveConstraint(
            model_name="persistentllmtier",
            name="persistentllmtier_max_excludes_premium",
        ),
        migrations.RemoveConstraint(
            model_name="profilepersistenttier",
            name="profilepersistenttier_max_excludes_premium",
        ),
        migrations.AlterUniqueTogether(
            name="browserllmtier",
            unique_together=set(),
        ),
        migrations.AlterUniqueTogether(
            name="persistentllmtier",
            unique_together=set(),
        ),
        migrations.AlterUniqueTogether(
            name="profilebrowsertier",
            unique_together=set(),
        ),
        migrations.AlterUniqueTogether(
            name="profilepersistenttier",
            unique_together=set(),
        ),
        migrations.RemoveField(
            model_name="browsertierendpoint",
            name="is_premium",
        ),
        migrations.RemoveField(
            model_name="persistenttierendpoint",
            name="is_max",
        ),
        migrations.RemoveField(
            model_name="persistenttierendpoint",
            name="is_premium",
        ),
        migrations.RemoveField(
            model_name="profilebrowsertierendpoint",
            name="is_premium",
        ),
        migrations.RemoveField(
            model_name="profilepersistenttierendpoint",
            name="is_max",
        ),
        migrations.RemoveField(
            model_name="profilepersistenttierendpoint",
            name="is_premium",
        ),
        migrations.RunPython(migrations.RunPython.noop, collapse_intelligence_tiers_for_rollback),
        migrations.AlterUniqueTogether(
            name="browserllmtier",
            unique_together={("policy", "order", "intelligence_tier")},
        ),
        migrations.AlterUniqueTogether(
            name="persistentllmtier",
            unique_together={("token_range", "order", "intelligence_tier")},
        ),
        migrations.AlterUniqueTogether(
            name="profilebrowsertier",
            unique_together={("profile", "order", "intelligence_tier")},
        ),
        migrations.AlterUniqueTogether(
            name="profilepersistenttier",
            unique_together={("token_range", "order", "intelligence_tier")},
        ),
        migrations.RemoveField(
            model_name="browserllmtier",
            name="is_premium",
        ),
        migrations.RemoveField(
            model_name="persistentllmtier",
            name="credit_multiplier",
        ),
        migrations.RemoveField(
            model_name="persistentllmtier",
            name="is_max",
        ),
        migrations.RemoveField(
            model_name="persistentllmtier",
            name="is_premium",
        ),
        migrations.RemoveField(
            model_name="profilebrowsertier",
            name="is_premium",
        ),
        migrations.RemoveField(
            model_name="profilepersistenttier",
            name="credit_multiplier",
        ),
        migrations.RemoveField(
            model_name="profilepersistenttier",
            name="is_max",
        ),
        migrations.RemoveField(
            model_name="profilepersistenttier",
            name="is_premium",
        ),
        migrations.RemoveField(
            model_name="persistentagent",
            name="preferred_llm_tier_value",
        ),
        migrations.AlterModelOptions(
            name="browserllmtier",
            options={"ordering": ["policy__name", "intelligence_tier__rank", "order"]},
        ),
        migrations.AlterModelOptions(
            name="persistentllmtier",
            options={"ordering": ["token_range__min_tokens", "intelligence_tier__rank", "order"]},
        ),
        migrations.AlterModelOptions(
            name="profilebrowsertier",
            options={"ordering": ["profile", "intelligence_tier__rank", "order"]},
        ),
        migrations.AlterModelOptions(
            name="profilepersistenttier",
            options={
                "ordering": [
                    "token_range__profile",
                    "token_range__min_tokens",
                    "intelligence_tier__rank",
                    "order",
                ]
            },
        ),
    ]
