# Generated by Django 5.1.7 on 2025-03-19 13:11

import django.db.models.deletion
import django.db.models.expressions
from django.db import migrations, models
from django.db.models import F, Min


def copy_year_released(apps, schema_editor):
    Game = apps.get_model("games", "Game")
    Game.objects.update(original_year_released=F("year_released"))


def set_abandoned_status(apps, schema_editor):
    Game = apps.get_model("games", "Game")
    Game = apps.get_model("games", "Game")
    PlayEvent = apps.get_model("games", "PlayEvent")

    Game.objects.filter(purchases__date_refunded__isnull=False).update(status="a")
    Game.objects.filter(purchases__date_dropped__isnull=False).update(status="a")

    finished = Game.objects.filter(purchases__date_finished__isnull=False)

    for game in finished:
        for purchase in game.purchases.all():
            first_session = game.sessions.filter(
                timestamp_start__gte=purchase.date_purchased
            ).aggregate(Min("timestamp_start"))["timestamp_start__min"]
            first_session_date = first_session.date() if first_session else None
            if purchase.date_finished:
                play_event = PlayEvent(
                    game=game,
                    started=first_session_date
                    if first_session_date
                    else purchase.date_purchased,
                    ended=purchase.date_finished,
                )
                play_event.save()


def create_game_status_changes(apps, schema_editor):
    Game = apps.get_model("games", "Game")
    GameStatusChange = apps.get_model("games", "GameStatusChange")

    # if game has any sessions, find the earliest session and create a status change from unplayed to played with that sessions's timestamp_start
    for game in Game.objects.filter(sessions__isnull=False).distinct():
        if game.sessions.exists():
            earliest_session = game.sessions.earliest()
            GameStatusChange.objects.create(
                game=game,
                old_status="u",
                new_status="p",
                timestamp=earliest_session.timestamp_start,
            )

    for game in Game.objects.filter(purchases__date_dropped__isnull=False):
        GameStatusChange.objects.create(
            game=game,
            old_status="p",
            new_status="a",
            timestamp=game.purchases.first().date_dropped,
        )

    for game in Game.objects.filter(purchases__date_refunded__isnull=False):
        GameStatusChange.objects.create(
            game=game,
            old_status="p",
            new_status="a",
            timestamp=game.purchases.first().date_refunded,
        )

    # check if game has any playevents, if so create a status change from current status to finished based on playevent's ended date
    # consider only the first playevent
    for game in Game.objects.filter(playevents__isnull=False):
        first_playevent = game.playevents.first()
        GameStatusChange.objects.create(
            game=game,
            old_status="p",
            new_status="f",
            timestamp=first_playevent.ended,
        )


class Migration(migrations.Migration):
    dependencies = [
        ("games", "0007_game_updated_at"),
    ]

    operations = [
        migrations.AddField(
            model_name="game",
            name="original_year_released",
            field=models.IntegerField(blank=True, default=None, null=True),
        ),
        migrations.RunPython(copy_year_released),
        migrations.CreateModel(
            name="GameStatusChange",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                (
                    "old_status",
                    models.CharField(
                        blank=True,
                        choices=[
                            ("u", "Unplayed"),
                            ("p", "Played"),
                            ("f", "Finished"),
                            ("r", "Retired"),
                            ("a", "Abandoned"),
                        ],
                        max_length=1,
                        null=True,
                    ),
                ),
                (
                    "new_status",
                    models.CharField(
                        choices=[
                            ("u", "Unplayed"),
                            ("p", "Played"),
                            ("f", "Finished"),
                            ("r", "Retired"),
                            ("a", "Abandoned"),
                        ],
                        max_length=1,
                    ),
                ),
                ("timestamp", models.DateTimeField(null=True)),
                (
                    "game",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="status_changes",
                        to="games.game",
                    ),
                ),
            ],
            options={
                "ordering": ["-timestamp"],
            },
        ),
        migrations.CreateModel(
            name="PlayEvent",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("started", models.DateField(blank=True, null=True)),
                ("ended", models.DateField(blank=True, null=True)),
                (
                    "days_to_finish",
                    models.GeneratedField(
                        db_persist=True,
                        expression=django.db.models.expressions.RawSQL(
                            "\n            COALESCE(\n                CASE \n                    WHEN date(ended) = date(started) THEN 1\n                    ELSE julianday(ended) - julianday(started)\n                END, 0\n            )\n            ",
                            [],
                        ),
                        output_field=models.IntegerField(),
                    ),
                ),
                ("note", models.CharField(blank=True, default="", max_length=255)),
                ("created_at", models.DateTimeField(auto_now_add=True)),
                ("updated_at", models.DateTimeField(auto_now=True)),
                (
                    "game",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="playevents",
                        to="games.game",
                    ),
                ),
            ],
        ),
        migrations.RunPython(set_abandoned_status),
        migrations.RunPython(create_game_status_changes),
    ]
