"""initial user schema

Revision ID: 001
Revises: 
Create Date: 2026-01-01 00:00:00.000000

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


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


def upgrade() -> None:
    """Create all user data tables."""
    
    # 1. User Sessions Table
    op.create_table(
        'user_sessions',
        sa.Column('id', sa.BigInteger().with_variant(sa.Integer, "sqlite"), primary_key=True),
        sa.Column('user_id', sa.Integer(), sa.ForeignKey('mtgonline_users.id', ondelete='CASCADE'), nullable=False),
        sa.Column('session_token_hash', sa.String(255), unique=True, nullable=False),
        sa.Column('ip_address', sa.String(45), nullable=True),
        sa.Column('user_agent', sa.Text(), nullable=True),
        sa.Column('created_at', sa.DateTime(), server_default=sa.func.now()),
        sa.Column('expires_at', sa.DateTime(), nullable=False),
        sa.Column('is_active', sa.Boolean(), default=True),
    )
    op.create_index('idx_sessions_user', 'user_sessions', ['user_id'])
    op.create_index('idx_sessions_token', 'user_sessions', ['session_token_hash'])
    op.create_index('idx_sessions_expires', 'user_sessions', ['expires_at'])

    # 2. Deck Versions Table
    op.create_table(
        'deck_versions',
        sa.Column('id', sa.BigInteger().with_variant(sa.Integer, "sqlite"), primary_key=True),
        sa.Column('deck_id', sa.Integer(), sa.ForeignKey('mtgonline_decklist_files.id', ondelete='CASCADE'), nullable=False),
        sa.Column('version_number', sa.Integer(), nullable=False),
        sa.Column('content', sa.Text(), nullable=False),
        sa.Column('status', sa.String(20), server_default='DRAFT'),
        sa.Column('comment', sa.Text(), nullable=True),
        sa.Column('created_at', sa.DateTime(), server_default=sa.func.now()),
    )
    op.create_index('idx_deck_versions_deck', 'deck_versions', ['deck_id'])

    # 4. Game Replays Table
    op.create_table(
        'game_replays',
        sa.Column('id', sa.BigInteger().with_variant(sa.Integer, "sqlite"), primary_key=True),
        sa.Column('game_uuid', sa.String(36), unique=True, nullable=False),
        sa.Column('room_id', sa.Integer(), sa.ForeignKey('mtgonline_rooms.id'), nullable=True),
        sa.Column('game_type', sa.String(50), nullable=True),
        sa.Column('format', sa.String(50), nullable=True),
        sa.Column('duration_seconds', sa.Integer(), nullable=True),
        sa.Column('start_time', sa.DateTime(), nullable=False),
        sa.Column('end_time', sa.DateTime(), nullable=True),
        sa.Column('status', sa.String(20), server_default='IN_PROGRESS'),
        sa.Column('replay_data', sa.JSON(), nullable=True),
        sa.Column('created_at', sa.DateTime(), server_default=sa.func.now()),
        sa.Column('updated_at', sa.DateTime(), server_default=sa.func.now(), onupdate=sa.func.now()),
    )
    op.create_index('idx_replays_room', 'game_replays', ['room_id'])
    op.create_index('idx_replays_start', 'game_replays', ['start_time'])
    op.create_index('idx_replays_status', 'game_replays', ['status'])

    # 5. Replay Players Table
    op.create_table(
        'replay_players',
        sa.Column('id', sa.BigInteger().with_variant(sa.Integer, "sqlite"), primary_key=True),
        sa.Column('replay_id', sa.BigInteger(), sa.ForeignKey('game_replays.id', ondelete='CASCADE'), nullable=False),
        sa.Column('user_id', sa.Integer(), sa.ForeignKey('mtgonline_users.id'), nullable=False),
        sa.Column('position', sa.Integer(), nullable=True),
        sa.Column('deck_id', sa.Integer(), sa.ForeignKey('mtgonline_decklist_files.id'), nullable=True),
        sa.Column('won', sa.Boolean(), nullable=True),
        sa.Column('lost', sa.Boolean(), nullable=True),
        sa.Column('concession', sa.Boolean(), default=False),
        sa.Column('turn_one', sa.Boolean(), default=False),
        sa.Column('created_at', sa.DateTime(), server_default=sa.func.now()),
    )
    op.create_index('idx_replay_players_replay', 'replay_players', ['replay_id'])
    op.create_index('idx_replay_players_user', 'replay_players', ['user_id'])

    # 6. Game Outcomes Table
    op.create_table(
        'game_outcomes',
        sa.Column('id', sa.BigInteger().with_variant(sa.Integer, "sqlite"), primary_key=True),
        sa.Column('user_id', sa.Integer(), sa.ForeignKey('mtgonline_users.id'), nullable=False),
        sa.Column('game_uuid', sa.String(36), sa.ForeignKey('game_replays.game_uuid'), nullable=False),
        sa.Column('outcome', sa.String(20), nullable=False),
        sa.Column('opponent_id', sa.Integer(), sa.ForeignKey('mtgonline_users.id'), nullable=True),
        sa.Column('format', sa.String(50), nullable=True),
        sa.Column('rating_before', sa.Integer(), nullable=True),
        sa.Column('rating_after', sa.Integer(), nullable=True),
        sa.Column('rating_change', sa.Integer(), nullable=True),
        sa.Column('created_at', sa.DateTime(), server_default=sa.func.now()),
    )
    op.create_index('idx_outcomes_user', 'game_outcomes', ['user_id'])
    op.create_index('idx_outcomes_game', 'game_outcomes', ['game_uuid'])
    op.create_index('idx_outcomes_outcome', 'game_outcomes', ['outcome'])

    # 7. User Statistics Table
    op.create_table(
        'user_statistics',
        sa.Column('user_id', sa.Integer(), sa.ForeignKey('mtgonline_users.id'), primary_key=True),
        sa.Column('total_games', sa.Integer(), default=0),
        sa.Column('total_wins', sa.Integer(), default=0),
        sa.Column('total_losses', sa.Integer(), default=0),
        sa.Column('total_concessions', sa.Integer(), default=0),
        sa.Column('win_rate', sa.Float(), default=0.0),
        sa.Column('current_streak', sa.Integer(), default=0),
        sa.Column('best_streak', sa.Integer(), default=0),
        sa.Column('average_rating', sa.Float(), default=0.0),
        sa.Column('last_game_date', sa.DateTime(), nullable=True),
        sa.Column('updated_at', sa.DateTime(), server_default=sa.func.now(), onupdate=sa.func.now()),
    )

    # 8. User Card Collection Table
    op.create_table(
        'user_card_collection',
        sa.Column('id', sa.BigInteger().with_variant(sa.Integer, "sqlite"), primary_key=True),
        sa.Column('user_id', sa.Integer(), sa.ForeignKey('mtgonline_users.id', ondelete='CASCADE'), nullable=False),
        sa.Column('card_id', sa.Integer(), nullable=False),
        sa.Column('quantity', sa.Integer(), default=1),
        sa.Column('condition', sa.String(20), server_default='NEAR_MINT'),
        sa.Column('language', sa.String(5), server_default='EN'),
        sa.Column('is_foil', sa.Boolean(), default=False),
        sa.Column('is_alt_art', sa.Boolean(), default=False),
        sa.Column('acquired_date', sa.DateTime(), server_default=sa.func.now()),
        sa.Column('acquisition_method', sa.String(50), nullable=True),
        sa.Column('notes', sa.Text(), nullable=True),
        sa.Column('created_at', sa.DateTime(), server_default=sa.func.now()),
        sa.Column('updated_at', sa.DateTime(), server_default=sa.func.now(), onupdate=sa.func.now()),
    )
    op.create_index('idx_collection_user_card', 'user_card_collection', ['user_id', 'card_id'])
    op.create_unique_constraint('uq_collection_unique', 'user_card_collection', ['user_id', 'card_id', 'is_foil', 'is_alt_art'])

    # 9. Card Wishlist Table
    op.create_table(
        'card_wishlist',
        sa.Column('id', sa.BigInteger().with_variant(sa.Integer, "sqlite"), primary_key=True),
        sa.Column('user_id', sa.Integer(), sa.ForeignKey('mtgonline_users.id', ondelete='CASCADE'), nullable=False),
        sa.Column('card_id', sa.Integer(), nullable=False),
        sa.Column('max_price', sa.Float(), nullable=True),
        sa.Column('notes', sa.Text(), nullable=True),
        sa.Column('created_at', sa.DateTime(), server_default=sa.func.now()),
    )
    op.create_unique_constraint('uq_wishlist_user_card', 'card_wishlist', ['user_id', 'card_id'])

    # 10. User Groups Table
    op.create_table(
        'user_groups',
        sa.Column('id', sa.BigInteger().with_variant(sa.Integer, "sqlite"), primary_key=True),
        sa.Column('name', sa.String(100), nullable=False),
        sa.Column('description', sa.Text(), nullable=True),
        sa.Column('owner_id', sa.Integer(), sa.ForeignKey('mtgonline_users.id'), nullable=False),
        sa.Column('is_public', sa.Boolean(), default=True),
        sa.Column('max_members', sa.Integer(), default=50),
        sa.Column('created_at', sa.DateTime(), server_default=sa.func.now()),
        sa.Column('updated_at', sa.DateTime(), server_default=sa.func.now(), onupdate=sa.func.now()),
    )
    op.create_index('idx_groups_owner', 'user_groups', ['owner_id'])

    # 11. Group Members Table
    op.create_table(
        'group_members',
        sa.Column('id', sa.BigInteger().with_variant(sa.Integer, "sqlite"), primary_key=True),
        sa.Column('group_id', sa.BigInteger(), sa.ForeignKey('user_groups.id', ondelete='CASCADE'), nullable=False),
        sa.Column('user_id', sa.Integer(), sa.ForeignKey('mtgonline_users.id'), nullable=False),
        sa.Column('role', sa.String(20), server_default='MEMBER'),
        sa.Column('joined_at', sa.DateTime(), server_default=sa.func.now()),
    )
    op.create_index('idx_members_group', 'group_members', ['group_id'])
    op.create_index('idx_members_user', 'group_members', ['user_id'])
    op.create_unique_constraint('uq_group_member', 'group_members', ['group_id', 'user_id'])

    # 12. Group Chat Messages Table
    op.create_table(
        'group_chat_messages',
        sa.Column('id', sa.BigInteger().with_variant(sa.Integer, "sqlite"), primary_key=True),
        sa.Column('group_id', sa.BigInteger(), sa.ForeignKey('user_groups.id', ondelete='CASCADE'), nullable=False),
        sa.Column('sender_id', sa.Integer(), sa.ForeignKey('mtgonline_users.id'), nullable=False),
        sa.Column('message', sa.Text(), nullable=False),
        sa.Column('created_at', sa.DateTime(), server_default=sa.func.now()),
    )
    op.create_index('idx_group_messages_group', 'group_chat_messages', ['group_id'])
    op.create_index('idx_group_messages_sender', 'group_chat_messages', ['sender_id'])
    op.create_index('idx_group_messages_created', 'group_chat_messages', ['created_at'])

    # 13. User Networks Table
    op.create_table(
        'user_networks',
        sa.Column('id', sa.BigInteger().with_variant(sa.Integer, "sqlite"), primary_key=True),
        sa.Column('name', sa.String(100), nullable=False),
        sa.Column('description', sa.Text(), nullable=True),
        sa.Column('creator_id', sa.Integer(), sa.ForeignKey('mtgonline_users.id'), nullable=False),
        sa.Column('is_public', sa.Boolean(), default=True),
        sa.Column('created_at', sa.DateTime(), server_default=sa.func.now()),
    )

    # 14. Network Members Table
    op.create_table(
        'network_members',
        sa.Column('id', sa.BigInteger().with_variant(sa.Integer, "sqlite"), primary_key=True),
        sa.Column('network_id', sa.BigInteger(), sa.ForeignKey('user_networks.id', ondelete='CASCADE'), nullable=False),
        sa.Column('user_id', sa.Integer(), sa.ForeignKey('mtgonline_users.id'), nullable=False),
        sa.Column('role', sa.String(20), server_default='MEMBER'),
        sa.Column('joined_at', sa.DateTime(), server_default=sa.func.now()),
    )
    op.create_index('idx_network_members_network', 'network_members', ['network_id'])
    op.create_index('idx_network_members_user', 'network_members', ['user_id'])
    op.create_unique_constraint('uq_network_member', 'network_members', ['network_id', 'user_id'])

    # 15. User Preferences Table
    op.create_table(
        'user_preferences',
        sa.Column('user_id', sa.Integer(), sa.ForeignKey('mtgonline_users.id'), primary_key=True),
        sa.Column('theme', sa.String(20), server_default='light'),
        sa.Column('notifications_enabled', sa.Boolean(), default=True),
        sa.Column('email_notifications', sa.Boolean(), default=True),
        sa.Column('auto_save_decks', sa.Boolean(), default=True),
        sa.Column('default_format', sa.String(50), server_default='standard'),
        sa.Column('language', sa.String(5), server_default='EN'),
        sa.Column('updated_at', sa.DateTime(), server_default=sa.func.now(), onupdate=sa.func.now()),
    )

    # 16. User Activity Log Table
    op.create_table(
        'user_activity_log',
        sa.Column('id', sa.BigInteger().with_variant(sa.Integer, "sqlite"), primary_key=True),
        sa.Column('user_id', sa.Integer(), sa.ForeignKey('mtgonline_users.id'), nullable=False),
        sa.Column('activity_type', sa.String(50), nullable=False),
        sa.Column('activity_data', sa.JSON(), nullable=True),
        sa.Column('ip_address', sa.String(45), nullable=True),
        sa.Column('created_at', sa.DateTime(), server_default=sa.func.now()),
    )
    op.create_index('idx_activity_user', 'user_activity_log', ['user_id'])
    op.create_index('idx_activity_type', 'user_activity_log', ['activity_type'])
    op.create_index('idx_activity_created', 'user_activity_log', ['created_at'])


def downgrade() -> None:
    """Drop all user data tables."""
    op.drop_table('user_activity_log')
    op.drop_table('user_preferences')
    op.drop_table('network_members')
    op.drop_table('user_networks')
    op.drop_table('group_chat_messages')
    op.drop_table('group_members')
    op.drop_table('user_groups')
    op.drop_table('card_wishlist')
    op.drop_table('user_card_collection')
    op.drop_table('user_statistics')
    op.drop_table('game_outcomes')
    op.drop_table('replay_players')
    op.drop_table('game_replays')
    op.drop_table('deck_versions')
    op.drop_table('user_sessions')
