# Generated by Django 5.2.9 on 2025-12-31
# API Key Security Migration: Add hash-based storage

import hashlib
from django.db import migrations, models


def hash_existing_keys(apps, schema_editor):
    """
    Hash all existing API keys.

    This migration:
    1. Computes SHA-256 hash of each plaintext key
    2. Stores the hash in key_hash field
    3. Stores the prefix in key_prefix field
    4. Keeps the original key for rollback (will be removed later)
    """
    GrpcApiKey = apps.get_model("grpc", "GrpcApiKey")

    for api_key in GrpcApiKey.objects.all():
        if api_key.key and not api_key.key_hash:
            # Compute SHA-256 hash
            key_hash = hashlib.sha256(api_key.key.encode("utf-8")).hexdigest()
            # Store prefix for display
            key_prefix = api_key.key[:8]

            api_key.key_hash = key_hash
            api_key.key_prefix = key_prefix
            api_key.save(update_fields=["key_hash", "key_prefix"])


def reverse_hash_keys(apps, schema_editor):
    """
    Reverse migration: Clear hash fields (keys remain in plaintext).

    Note: This does NOT restore keys that were created after migration
    with only hash storage.
    """
    GrpcApiKey = apps.get_model("grpc", "GrpcApiKey")
    GrpcApiKey.objects.all().update(key_hash=None, key_prefix=None)


class Migration(migrations.Migration):
    """
    Add secure hash-based storage for API keys.

    Security improvements:
    - key_hash: SHA-256 hash for validation (no plaintext comparison)
    - key_prefix: First 8 chars for display/identification
    - key: Made nullable for new keys (will be removed in future)

    Migration is reversible for rollback within 7 days.
    After that, the `key` field will be removed permanently.
    """

    dependencies = [
        ("grpc", "0009_grpcagentconnectionstate_grpcagentconnectionmetric_and_more"),
    ]

    operations = [
        # Step 1: Add key_hash field (nullable initially)
        migrations.AddField(
            model_name="grpcapikey",
            name="key_hash",
            field=models.CharField(
                blank=True,
                db_index=True,
                help_text="SHA-256 hash of the API key",
                max_length=64,
                null=True,
                unique=True,
            ),
        ),
        # Step 2: Add key_prefix field (nullable initially)
        migrations.AddField(
            model_name="grpcapikey",
            name="key_prefix",
            field=models.CharField(
                blank=True,
                db_index=True,
                help_text="First 8 characters of the key (for display only)",
                max_length=8,
                null=True,
            ),
        ),
        # Step 3: Hash existing keys
        migrations.RunPython(hash_existing_keys, reverse_hash_keys),
        # Step 4: Make original key field nullable (for new keys without plaintext)
        migrations.AlterField(
            model_name="grpcapikey",
            name="key",
            field=models.CharField(
                blank=True,
                db_index=True,
                default=None,
                help_text="DEPRECATED: Use key_hash instead",
                max_length=64,
                null=True,
                unique=True,
            ),
        ),
    ]
