"""v0.1.4 migration

Revision ID: 1bce2bd27873
Revises: 
Create Date: 2024-02-10 15:21:36.689455

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa

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


def upgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('users',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('name', sa.String(length=250), nullable=False, comment='User real name (May include spaces)'),
    sa.Column('username', sa.String(length=250), nullable=False, comment='User username (letters, numbers, and dots allowed)'),
    sa.Column('email', sa.String(length=250), nullable=False, comment='User email (max 250 characters)'),
    sa.Column('password', sa.String(length=100), nullable=False, comment='User password (hash)'),
    sa.Column('city', sa.String(length=250), nullable=True, comment='User city'),
    sa.Column('birthdate', sa.Date(), nullable=True, comment='User birthdate (date)'),
    sa.Column('preferred_language', sa.String(length=5), nullable=False, comment='User preferred language (en, pt, others)'),
    sa.Column('gender', sa.Integer(), nullable=False, comment='User gender (one digit)(1 - male, 2 - female)'),
    sa.Column('access_type', sa.Integer(), nullable=False, comment='User type (one digit)(1 - user, 2 - admin)'),
    sa.Column('photo_path', sa.String(length=250), nullable=True, comment='User photo path'),
    sa.Column('photo_path_aux', sa.String(length=250), nullable=True, comment='Auxiliary photo path'),
    sa.Column('is_active', sa.Integer(), nullable=False, comment='Is user active (1 - active, 2 - not active)'),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_users_email'), 'users', ['email'], unique=True)
    op.create_index(op.f('ix_users_username'), 'users', ['username'], unique=True)
    op.create_table('access_tokens',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('token', sa.String(length=256), nullable=False, comment='User token'),
    sa.Column('user_id', sa.Integer(), nullable=False, comment='User ID that the token belongs'),
    sa.Column('created_at', sa.DateTime(), nullable=False, comment='Token creation date (date)'),
    sa.Column('expires_at', sa.DateTime(), nullable=False, comment='Token expiration date (date)'),
    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_access_tokens_user_id'), 'access_tokens', ['user_id'], unique=False)
    op.create_table('followers',
    sa.Column('follower_id', sa.Integer(), nullable=False, comment='ID of the follower user'),
    sa.Column('following_id', sa.Integer(), nullable=False, comment='ID of the following user'),
    sa.Column('is_accepted', sa.Boolean(), nullable=False, comment='Whether the follow request is accepted or not'),
    sa.ForeignKeyConstraint(['follower_id'], ['users.id'], ),
    sa.ForeignKeyConstraint(['following_id'], ['users.id'], ),
    sa.PrimaryKeyConstraint('follower_id', 'following_id')
    )
    op.create_index(op.f('ix_followers_follower_id'), 'followers', ['follower_id'], unique=False)
    op.create_index(op.f('ix_followers_following_id'), 'followers', ['following_id'], unique=False)
    op.create_table('gear',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('brand', sa.String(length=250), nullable=True, comment='Gear brand (May include spaces)'),
    sa.Column('model', sa.String(length=250), nullable=True, comment='Gear model (May include spaces)'),
    sa.Column('nickname', sa.String(length=250), nullable=False, comment='Gear nickname (May include spaces)'),
    sa.Column('gear_type', sa.Integer(), nullable=False, comment='Gear type (1 - bike, 2 - shoes, 3 - wetsuit)'),
    sa.Column('user_id', sa.Integer(), nullable=False, comment='User ID that the gear belongs to'),
    sa.Column('created_at', sa.DateTime(), nullable=False, comment='Gear creation date (date)'),
    sa.Column('is_active', sa.Integer(), nullable=False, comment='Is gear active (0 - not active, 1 - active)'),
    sa.Column('strava_gear_id', sa.String(length=45), nullable=True, comment='Strava gear ID'),
    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('strava_gear_id')
    )
    op.create_index(op.f('ix_gear_nickname'), 'gear', ['nickname'], unique=True)
    op.create_table('users_integrations',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('user_id', sa.Integer(), nullable=False, comment='User ID that the token belongs'),
    sa.Column('strava_state', sa.String(length=45), nullable=True),
    sa.Column('strava_token', sa.String(length=250), nullable=True),
    sa.Column('strava_refresh_token', sa.String(length=250), nullable=True),
    sa.Column('strava_token_expires_at', sa.DateTime(), nullable=True),
    sa.Column('strava_sync_gear', sa.Boolean(), nullable=False, comment='Whether Strava gear is to be synced'),
    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_users_integrations_user_id'), 'users_integrations', ['user_id'], unique=False)
    op.create_table('activities',
    sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
    sa.Column('user_id', sa.Integer(), nullable=False, comment='User ID that the activity belongs'),
    sa.Column('name', sa.String(length=250), nullable=True, comment='Activity name (May include spaces)'),
    sa.Column('description', sa.String(length=2500), nullable=True, comment='Activity description (May include spaces)'),
    sa.Column('distance', sa.Integer(), nullable=False, comment='Distance in meters'),
    sa.Column('activity_type', sa.Integer(), nullable=False, comment='Gear type (1 - mountain bike, 2 - gravel bike, ...)'),
    sa.Column('start_time', sa.DateTime(), nullable=False, comment='Activity start date (datetime)'),
    sa.Column('end_time', sa.DateTime(), nullable=False, comment='Activity end date (datetime)'),
    sa.Column('city', sa.String(length=250), nullable=True, comment='Activity city (May include spaces)'),
    sa.Column('town', sa.String(length=250), nullable=True, comment='Activity town (May include spaces)'),
    sa.Column('country', sa.String(length=250), nullable=True, comment='Activity country (May include spaces)'),
    sa.Column('created_at', sa.DateTime(), nullable=False, comment='Activity creation date (datetime)'),
    sa.Column('elevation_gain', sa.Integer(), nullable=False, comment='Elevation gain in meters'),
    sa.Column('elevation_loss', sa.Integer(), nullable=False, comment='Elevation loss in meters'),
    sa.Column('pace', sa.DECIMAL(precision=20, scale=10), nullable=False, comment='Pace seconds per meter (s/m)'),
    sa.Column('average_speed', sa.DECIMAL(precision=20, scale=10), nullable=False, comment='Average speed seconds per meter (s/m)'),
    sa.Column('average_power', sa.Integer(), nullable=False, comment='Average power (watts)'),
    sa.Column('calories', sa.Integer(), nullable=True, comment='The number of kilocalories consumed during this activity'),
    sa.Column('visibility', sa.Integer(), nullable=False, comment='0 - public, 1 - followers, 2 - private'),
    sa.Column('gear_id', sa.Integer(), nullable=True, comment='Gear ID associated with this activity'),
    sa.Column('strava_gear_id', sa.String(length=45), nullable=True, comment='Strava gear ID'),
    sa.Column('strava_activity_id', sa.BigInteger(), nullable=True, comment='Strava activity ID'),
    sa.ForeignKeyConstraint(['gear_id'], ['gear.id'], ondelete='SET NULL'),
    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('strava_activity_id')
    )
    op.create_index(op.f('ix_activities_gear_id'), 'activities', ['gear_id'], unique=False)
    op.create_index(op.f('ix_activities_user_id'), 'activities', ['user_id'], unique=False)
    op.create_table('activities_streams',
    sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
    sa.Column('activity_id', sa.Integer(), nullable=False, comment='Activity ID that the activity stream belongs'),
    sa.Column('stream_type', sa.Integer(), nullable=False, comment='Stream type (1 - HR, 2 - Power, 3 - Cadence, 4 - Elevation, 5 - Velocity, 6 - Pace, 7 - lat/lon)'),
    sa.Column('stream_waypoints', sa.JSON(), nullable=False),
    sa.Column('strava_activity_stream_id', sa.BigInteger(), nullable=True, comment='Strava activity stream ID'),
    sa.ForeignKeyConstraint(['activity_id'], ['activities.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_activities_streams_activity_id'), 'activities_streams', ['activity_id'], unique=False)
    # Commands to insert a default user
    op.execute("""
    INSERT INTO users (name, username, email, password, preferred_language, gender, access_type, is_active) VALUES
    ('Admin', 'admin', 'admin@endurain.com', '8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918', 'en', 1, 2, 1);
    """)
    op.execute("""
    INSERT INTO users_integrations (user_id, strava_sync_gear) VALUES
    (1, false);
    """)
    # ### end Alembic commands ###


def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index(op.f('ix_activities_streams_activity_id'), table_name='activities_streams')
    op.drop_table('activities_streams')
    op.drop_index(op.f('ix_activities_user_id'), table_name='activities')
    op.drop_index(op.f('ix_activities_gear_id'), table_name='activities')
    op.drop_table('activities')
    op.drop_index(op.f('ix_users_integrations_user_id'), table_name='users_integrations')
    op.drop_table('users_integrations')
    op.drop_index(op.f('ix_gear_nickname'), table_name='gear')
    op.drop_table('gear')
    op.drop_index(op.f('ix_followers_following_id'), table_name='followers')
    op.drop_index(op.f('ix_followers_follower_id'), table_name='followers')
    op.drop_table('followers')
    op.drop_index(op.f('ix_access_tokens_user_id'), table_name='access_tokens')
    op.drop_table('access_tokens')
    op.drop_index(op.f('ix_users_username'), table_name='users')
    op.drop_index(op.f('ix_users_email'), table_name='users')
    op.drop_table('users')
    # ### end Alembic commands ###
