"""backfill user last_password_changed_at

PRD-006 — User Profile Management (data backfill)
Sets last_password_changed_at = created_at for all users where the column is
NULL, so that password-age calculations have a sensible baseline.

This migration is intentionally non-destructive:
  - It only fills NULL values; any future explicit password changes already
    recorded will not be overwritten.
  - The downgrade() is a deliberate no-op — rolling back a data backfill
    (setting last_password_changed_at back to NULL) would incorrectly
    re-expose those users as "never changed password", defeating the policy
    enforcement logic. A DBA must manually revert if truly required.

Revision ID: 20260316002a
Revises: 20260316001a
Create Date: 2026-03-16 00:00:01.000000

"""
from typing import Sequence, Union

from alembic import op

# ---------------------------------------------------------------------------
# Revision metadata
# ---------------------------------------------------------------------------
revision: str = '20260316002a'
down_revision: Union[str, Sequence[str], None] = '20260316001a'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


# ---------------------------------------------------------------------------
# upgrade
# ---------------------------------------------------------------------------

def upgrade() -> None:
    """
    Backfill last_password_changed_at with the account creation timestamp
    for every user that does not yet have an explicit value.

    Using a single bulk UPDATE is intentional:
      - Avoids N+1 row-by-row updates.
      - PostgreSQL will take a brief exclusive lock per-page but the overall
        operation is fast for typical user table sizes (< 1 M rows).
      - For very large tables (> 5 M rows) run this out-of-band with
        batched updates before applying the migration.
    """
    op.execute(
        """
        UPDATE users
        SET    last_password_changed_at = created_at
        WHERE  last_password_changed_at IS NULL
        """
    )


# ---------------------------------------------------------------------------
# downgrade — intentional no-op
# ---------------------------------------------------------------------------

def downgrade() -> None:
    """
    Data backfills are not safely reversible.

    Setting last_password_changed_at back to NULL would mean the password-age
    enforcement service treats all backfilled users as having never set a
    password, potentially triggering mass forced-resets on the next login
    cycle.

    If a full rollback is truly required, a DBA should manually evaluate
    which rows were backfilled and decide the appropriate corrective action.
    """
    pass
