"""Nextcloud integration: per-user username override + encrypted app password

Revision ID: 0016_nextcloud_integration
Revises: 0015_oidc_and_avatar
Create Date: 2026-04-26

Lets each mule-image user wire their account to a Nextcloud account so
photos can be browsed, indexed, and mutated under their own Nextcloud
file tree (`/mnt/library/homecloud/<nc_user>/files/...` mounted into the
backend + workers as `/nextcloud-users`). The OIDC `preferred_username`
claim is the default mapping; the override field handles cases where the
authentik username and the Nextcloud username don't match.

  1. users.nextcloud_username — default sourced from preferred_username
     on OIDC login (only when null), editable via PATCH /api/v1/auth/me.
  2. users.nextcloud_app_password_enc — Fernet-encrypted Nextcloud app
     password used for HTTP Basic auth on WebDAV calls. Set from the
     Settings UI; the cleartext is never persisted.
"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa

revision: str = "0016_nextcloud_integration"
down_revision: Union[str, None] = "0015_oidc_and_avatar"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
    conn = op.get_bind()

    for col_def in (
        "nextcloud_username VARCHAR",
        "nextcloud_app_password_enc VARCHAR",
    ):
        conn.execute(sa.text(f"ALTER TABLE users ADD COLUMN IF NOT EXISTS {col_def}"))

    # Index the username for the per-user path-scoping check on /browse
    # and /source-roots — keeps lookups fast even on tiny user tables.
    conn.execute(sa.text(
        "CREATE INDEX IF NOT EXISTS ix_users_nextcloud_username "
        "ON users (nextcloud_username)"
    ))


def downgrade() -> None:
    conn = op.get_bind()
    conn.execute(sa.text("DROP INDEX IF EXISTS ix_users_nextcloud_username"))
    for col in ("nextcloud_app_password_enc", "nextcloud_username"):
        conn.execute(sa.text(f"ALTER TABLE users DROP COLUMN IF EXISTS {col}"))
