"""backups: clear the backfilled lastseenat - it was a guess, and it showed.

0002 added lastseenat and backfilled it from collectedat, reasoning that the
last change was the last moment the config could be PROVEN current. On a fleet
that was wrong in practice: an unchanged config writes no revision, so a machine
whose settings last changed nine months ago got a nine-month-old lastseenat and
was immediately reported as a stopped backup. Every chain lit up at once, which
is worse than no card - it says the fleet is broken when it is fine.

The honest value is NULL: before this column existed, nothing recorded when a
config was last confirmed, and inventing a date does not change that. A chain
becomes measurable the first time its PC posts after the upgrade, which for
NTLARS is within a day.

So staleness now IGNORES a chain whose lastseenat is NULL, rather than falling
back to timestamps that mean something else.
"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = 'backups0003clearlastseen'
down_revision = 'backups0002lastseenat'
branch_labels = None
depends_on = None


def upgrade():
    columns = {c['name'] for c in
               sa.inspect(op.get_bind()).get_columns('backuprevisions')}
    if 'lastseenat' in columns:
        # SCOPED TO THE BACKFILL, not to every row. An unscoped UPDATE was
        # correct exactly once; re-running it destroys evidence, and this chain
        # HAS been re-running on MySQL (see the missing commit in
        # shopdb/plugins/alembic_template.py). A migration that deletes data has
        # to assume it will run twice.
        #
        # TWO CONDITIONS, and both are needed:
        #
        # 1. The backfill's actual signature is COALESCE(collectedat, createdat)
        #    - that is the expression 0002 wrote. Matching `lastseenat =
        #    collectedat` alone misses every row whose collectedat is NULL,
        #    because NULL comparison is never true, so exactly the rows carrying
        #    the most invented value would have kept it forever.
        #
        # 2. A date bound, because value equality on its own is not a signature
        #    on MySQL. db.DateTime is second-precision there (SQLite keeps
        #    microseconds, which is why no test could show this), and the
        #    collector writes collectedat and lastseenat in one statement - so a
        #    genuinely fresh revision that arrived without a payload collectedat
        #    has the two stamps equal to the second and would be read as a
        #    backfill and wiped.
        #
        # The cutoff is the day this correction ships. Everything the backfill
        # touched predates it by construction; anything created after it is a
        # live collection this migration must never touch.
        op.execute("UPDATE backuprevisions SET lastseenat = NULL "
                   "WHERE lastseenat = COALESCE(collectedat, createdat) "
                   "AND createdat < '2026-08-14 00:00:00'")


def downgrade():
    # Nothing to restore: the backfilled values were derived, not recorded.
    pass
