"""
Migration: Encrypt sensitive SiteSettings fields.

Changes field types to EncryptedCharField (Fernet AES encryption).
Existing plaintext values are re-encrypted in-place via RunPython.
Requires FIELD_ENCRYPTION_KEY in .env.
"""
from django.db import migrations
try:
    from encrypted_model_fields.fields import EncryptedCharField
    _HAS_ENCRYPTION = True
except ImportError:
    _HAS_ENCRYPTION = False
import django.db.models.fields


def encrypt_existing(apps, schema_editor):
    """Re-save all existing plaintext values so they are stored encrypted."""
    from django.conf import settings as _settings
    from django.db import connection

    key = getattr(_settings, 'FIELD_ENCRYPTION_KEY', '')
    if not key or not _HAS_ENCRYPTION:
        return  # No key = skip (dev without encryption configured)

    from cryptography.fernet import Fernet, InvalidToken
    f = Fernet(key.encode() if isinstance(key, str) else key)

    sensitive = [
        'stripe_secret_key',
        'recaptcha_secret_key',
        'twilio_account_sid',
        'twilio_auth_token',
        'openai_api_key',
    ]

    cols = ', '.join(sensitive)
    with connection.cursor() as cur:
        cur.execute(f'SELECT id, {cols} FROM pages_sitesettings')
        rows = cur.fetchall()

    for row in rows:
        id_ = row[0]
        updates = []
        for i, field in enumerate(sensitive):
            val = row[i + 1] or ''
            if not val:
                continue
            # Skip if already Fernet-encrypted (starts with gAAAAA)
            try:
                f.decrypt(val.encode())
                continue  # already encrypted
            except (InvalidToken, Exception):
                pass
            encrypted = f.encrypt(val.encode()).decode()
            updates.append((field, encrypted))

        if updates:
            set_clause = ', '.join(f'"{f}" = %s' for f, _ in updates)
            vals = [v for _, v in updates] + [id_]
            with connection.cursor() as cur:
                cur.execute(
                    f'UPDATE pages_sitesettings SET {set_clause} WHERE id = %s',
                    vals,
                )


def noop(apps, schema_editor):
    pass


class Migration(migrations.Migration):

    dependencies = [
        ('pages', '0019_alter_sitesettings_site_title_suffix'),
    ]

    operations = [
        # Step 1: encrypt existing plaintext values in DB
        migrations.RunPython(encrypt_existing, noop),

        # Step 2: tell Django these fields are now EncryptedCharField
        migrations.AlterField(
            model_name='sitesettings',
            name='stripe_secret_key',
            field=EncryptedCharField(blank=True) if _HAS_ENCRYPTION else django.db.models.fields.CharField(blank=True, max_length=200),
        ),
        migrations.AlterField(
            model_name='sitesettings',
            name='recaptcha_secret_key',
            field=EncryptedCharField(blank=True) if _HAS_ENCRYPTION else django.db.models.fields.CharField(blank=True, max_length=200),
        ),
        migrations.AlterField(
            model_name='sitesettings',
            name='twilio_account_sid',
            field=EncryptedCharField(blank=True) if _HAS_ENCRYPTION else django.db.models.fields.CharField(blank=True, max_length=100),
        ),
        migrations.AlterField(
            model_name='sitesettings',
            name='twilio_auth_token',
            field=EncryptedCharField(blank=True) if _HAS_ENCRYPTION else django.db.models.fields.CharField(blank=True, max_length=100),
        ),
        migrations.AlterField(
            model_name='sitesettings',
            name='openai_api_key',
            field=EncryptedCharField(blank=True) if _HAS_ENCRYPTION else django.db.models.fields.CharField(blank=True, max_length=200),
        ),
    ]
