# Generated by Django 4.2.15 on 2024-12-17 05:52
from collections.abc import Callable
from datetime import datetime
from typing import TYPE_CHECKING

from django.db import migrations, models
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps

from debusine.db.models.work_requests import workflow_flattened
from debusine.tasks.models import TaskTypes

if TYPE_CHECKING:
    from debusine.db.models import WorkRequest


def update_workflows_last_activity_at(
    apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
) -> None:
    """
    Update workflows last_activity_at.

    Most recent activity of a workflow is the latest
    completed_at/started_at of their children.
    """
    WorkRequest = apps.get_model("db", "WorkRequest")

    for work_request in WorkRequest.objects.filter(
        task_type=TaskTypes.WORKFLOW
    ):
        work_request.workflow_last_activity_at = workflow_last_activity_at(
            work_request
        )
        work_request.save()


def workflow_last_activity_at(work_request: "WorkRequest") -> datetime | None:
    """
    Return the datetime of the most recent workflow's child's activity.

    Iterates over all the work requests part of the workflow and
    returns the most recent activity between all of them.
    """
    assert work_request.task_type == TaskTypes.WORKFLOW
    last_activity: Callable[["WorkRequest"], datetime | None] = (
        lambda work_request: work_request.completed_at
        or work_request.started_at
    )
    # type-var: ignore because mypy reports
    # error: Value of type variable "SupportsRichComparisonT" of "max"
    # cannot be "datetime | None"
    #
    # But this is guarded via "if last_activity(child)"
    return max(  # type: ignore[type-var]
        [
            last_activity(child)
            for child in workflow_flattened(work_request)
            if last_activity(child)
        ],
        default=None,
    )


class Migration(migrations.Migration):
    dependencies = [
        ('db', '0109_scope_label_required_and_unique'),
    ]

    operations = [
        migrations.AddField(
            model_name='workrequest',
            name='workflow_last_activity_at',
            field=models.DateTimeField(blank=True, null=True),
        ),
        migrations.RunPython(
            update_workflows_last_activity_at, migrations.RunPython.noop
        ),
    ]
