"""conference invitees and avatars

Реализует раздел «Модель данных» ADR-003
(`docs/architecture/adr/003-conference-invitees.md`):
- новая таблица `conference_invitees` — приглашённые НА КОНФЕРЕНЦИЮ
  (зарегистрированный `user_id` ИЛИ внешний `email`, ровно одна identity);
  организатор в таблице не хранится (выводится из `conferences.owner_id`);
- `users.avatar_path` — путь к загруженному аватару,
  `NULL` — заглушка с инициалами на фронте.

Revision ID: d87681e12784
Revises: 504791847d4f
Create Date: 2026-07-19 12:03:06.294730

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = 'd87681e12784'
down_revision: Union[str, Sequence[str], None] = '504791847d4f'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
    """Upgrade schema."""
    op.create_table(
        'conference_invitees',
        sa.Column('id', sa.UUID(), server_default=sa.text('gen_random_uuid()'), nullable=False),
        sa.Column('conference_id', sa.UUID(), nullable=False),
        sa.Column('user_id', sa.UUID(), nullable=True),
        sa.Column('email', sa.String(length=255), nullable=True),
        sa.Column(
            'created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'),
            nullable=False,
        ),
        sa.CheckConstraint(
            '(user_id IS NOT NULL)::int + (email IS NOT NULL)::int = 1',
            name='ck_conference_invitees_single_identity',
        ),
        sa.ForeignKeyConstraint(['conference_id'], ['conferences.id'], ondelete='CASCADE'),
        sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
        sa.PrimaryKeyConstraint('id'),
    )
    # Частичные уникальные индексы (ADR-003, п.1): дубль по зарегистрированному
    # пользователю или по email (регистронезависимо — `lower(email)`, email
    # приложение хранит уже в lower-case, индекс — доп. страховка).
    op.create_index(
        'uq_conference_invitees_user',
        'conference_invitees',
        ['conference_id', 'user_id'],
        unique=True,
        postgresql_where=sa.text('user_id IS NOT NULL'),
    )
    op.execute(
        """
        CREATE UNIQUE INDEX uq_conference_invitees_email
        ON conference_invitees (conference_id, lower(email))
        WHERE email IS NOT NULL
        """
    )

    op.add_column('users', sa.Column('avatar_path', sa.String(length=512), nullable=True))


def downgrade() -> None:
    """Downgrade schema."""
    op.drop_column('users', 'avatar_path')

    op.execute('DROP INDEX IF EXISTS uq_conference_invitees_email')
    op.drop_index('uq_conference_invitees_user', table_name='conference_invitees')
    op.drop_table('conference_invitees')
