"""
Phase 4 — Goals, and the conversion of `Task.goal` into a real foreign key.

Generated by `makemigrations`, then edited to add `_drop_dangling_goal_links`
BEFORE the `AlterField`. That step is the whole reason this file was touched by
hand: the column is an integer today with no constraint behind it, so any value
in it that does not name a real goal makes the ALTER fail — and it fails at the
end of a migration that has already created a table, which is the worst place
to find out.

Right now every value is dangling, because `Goal` is created empty two
operations earlier. The step is written as the general case anyway, so that it
still does the right thing if this migration is ever replayed against a
database that has goals in it.

The column also changes NAME, `goal` to `goal_id`, because that is what Django
calls a foreign key's column. `AlterField` handles the rename; it is noted here
because a hand-written query against `lifey_api_task.goal` will stop working
after this runs.
"""

import django.db.models.deletion
from django.db import migrations, models


def _drop_dangling_goal_links(apps, schema_editor):
    """
    Null every `Task.goal` that does not name a goal that exists.

    A task pointing at a goal that was never created is a pointer at nothing,
    and it has been one since Phase 3 — the column was an integer precisely
    because there was no table to point at. Nulling it is not data loss: it is
    writing down what was already true.
    """
    Task = apps.get_model('lifey_api', 'Task')
    Goal = apps.get_model('lifey_api', 'Goal')
    real = Goal.objects.values_list('pk', flat=True)
    Task.objects.exclude(goal__in=list(real)).exclude(goal=None).update(goal=None)


class Migration(migrations.Migration):

    dependencies = [
        ('lifey_api', '0002_task'),
    ]

    operations = [
        migrations.CreateModel(
            name='Goal',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('title', models.CharField(blank=True, max_length=300)),
                ('notes', models.TextField(blank=True)),
                ('status', models.CharField(default='todo', max_length=16)),
                ('tags', models.JSONField(blank=True, default=list)),
                ('target_date', models.DateField(blank=True, null=True)),
                ('color', models.CharField(blank=True, max_length=16, null=True)),
                ('diagram', models.CharField(default='roadmap', max_length=16)),
                ('progress_fraction', models.FloatField(blank=True, null=True)),
                ('steps', models.JSONField(blank=True, default=list)),
                ('note_link', models.JSONField(blank=True, null=True)),
                ('properties', models.JSONField(blank=True, default=dict)),
                ('is_sample', models.BooleanField(default=False)),
                ('completed_at', models.DateTimeField(blank=True, null=True)),
                ('page', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='goals', to='lifey_api.page')),
            ],
            options={
                'ordering': ['id'],
            },
        ),
        migrations.RunPython(_drop_dangling_goal_links, migrations.RunPython.noop),
        migrations.AlterField(
            model_name='task',
            name='goal',
            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tasks', to='lifey_api.goal'),
        ),
        migrations.AddIndex(
            model_name='goal',
            index=models.Index(fields=['page', 'status'], name='lifey_api_g_page_id_7c9ac2_idx'),
        ),
        migrations.AddIndex(
            model_name='goal',
            index=models.Index(fields=['page', 'target_date'], name='lifey_api_g_page_id_306c13_idx'),
        ),
    ]
