"""v0.14.0 migration

Revision ID: 86b2e24e227e
Revises: 2fb0ae78dea9
Create Date: 2025-08-27 09:13:48.552042

"""

from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision: str = "86b2e24e227e"
down_revision: Union[str, None] = "2fb0ae78dea9"
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! ###
    # New users_goals table
    op.create_table(
        "users_goals",
        sa.Column("id", sa.Integer(), autoincrement=True, nullable=False),
        sa.Column(
            "user_id",
            sa.Integer(),
            nullable=False,
            comment="User ID that the goals belongs",
        ),
        sa.Column(
            "interval",
            sa.String(length=250),
            nullable=False,
            comment="Goal interval (e.g., 'daily', 'weekly', 'monthly', 'yearly')",
        ),
        sa.Column(
            "activity_type", sa.Integer(), nullable=False, comment="Activity type"
        ),
        sa.Column("goal_type", sa.Integer(), nullable=False, comment="Goal type"),
        sa.Column(
            "goal_calories",
            sa.Integer(),
            nullable=True,
            comment="Goal calories in kcal (e.g., 5000 for 5000 kcal)",
        ),
        sa.Column(
            "goal_activities_number",
            sa.Integer(),
            nullable=True,
            comment="Goal activities number (e.g., 5 for 5 activities)",
        ),
        sa.Column(
            "goal_distance",
            sa.Integer(),
            nullable=True,
            comment="Goal distance in meters (e.g., 10000 for 10 km)",
        ),
        sa.Column(
            "goal_elevation",
            sa.Integer(),
            nullable=True,
            comment="Goal elevation in meters (e.g., 1000 for 1000 m)",
        ),
        sa.Column(
            "goal_duration",
            sa.Integer(),
            nullable=True,
            comment="Goal duration in seconds (e.g., 3600 for 1 hours)",
        ),
        sa.ForeignKeyConstraint(["user_id"], ["users.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_users_goals_user_id"), "users_goals", ["user_id"], unique=False
    )
    # Gear table changes
    op.alter_column(
        "gear",
        "created_at",
        existing_type=postgresql.TIMESTAMP(),
        comment="Gear creation date (DateTime)",
        existing_comment="Gear creation date (DATETIME)",
        existing_nullable=False,
    )
    # Users table changes
    op.add_column(
        "users",
        sa.Column(
            "mfa_enabled",
            sa.Boolean(),
            nullable=True,
            comment="Whether MFA is enabled for this user",
        ),
    )
    op.execute(
        """
        UPDATE users
        SET mfa_enabled = false
        WHERE mfa_enabled IS NULL;
    """
    )
    op.alter_column(
        "users",
        "mfa_enabled",
        nullable=False,
        comment="Whether MFA is enabled for this user",
        existing_type=sa.Boolean(),
    )
    op.add_column(
        "users",
        sa.Column(
            "mfa_secret",
            sa.String(length=512),
            nullable=True,
            comment="User MFA secret for TOTP generation (encrypted at rest)",
        ),
    )
    # Password reset tokens table
    op.create_table(
        "password_reset_tokens",
        sa.Column(
            "id",
            sa.String(length=64),
            nullable=False,
        ),
        sa.Column(
            "user_id",
            sa.Integer(),
            nullable=False,
            comment="User ID that the password reset token belongs to",
        ),
        sa.Column(
            "token_hash",
            sa.String(length=128),
            nullable=False,
            comment="Hashed password reset token",
        ),
        sa.Column(
            "created_at",
            sa.DateTime(),
            nullable=False,
            comment="Token creation date (datetime)",
        ),
        sa.Column(
            "expires_at",
            sa.DateTime(),
            nullable=False,
            comment="Token expiration date (datetime)",
        ),
        sa.Column(
            "used",
            sa.Boolean(),
            nullable=False,
            comment="Token usage status (False - unused, True - used)",
        ),
        sa.ForeignKeyConstraint(["user_id"], ["users.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_password_reset_tokens_user_id"),
        "password_reset_tokens",
        ["user_id"],
        unique=False,
    )
    # ### end Alembic commands ###


def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    # Drop password reset tokens table
    op.drop_index(
        op.f("ix_password_reset_tokens_user_id"), table_name="password_reset_tokens"
    )
    op.drop_table("password_reset_tokens")
    # Drop users columns
    op.drop_column("users", "mfa_secret")
    op.drop_column("users", "mfa_enabled")
    # Change gear.created_at column to original value
    op.alter_column(
        "gear",
        "created_at",
        existing_type=postgresql.TIMESTAMP(),
        comment="Gear creation date (DATETIME)",
        existing_comment="Gear creation date (DateTime)",
        existing_nullable=False,
    )
    # Drop table users_goals
    op.drop_index(op.f("ix_users_goals_user_id"), table_name="users_goals")
    op.drop_table("users_goals")
    # ### end Alembic commands ###
