"""add_invitation_tables

Revision ID: f4f5b93cbb16
Revises: 45e411faf2e7
Create Date: 2026-01-22 12:41:17.114044

"""

from collections.abc import Sequence

import sqlalchemy as sa
from alembic_postgresql_enum import TableReference
from sqlalchemy.dialects import postgresql

from alembic import op

# revision identifiers, used by Alembic.
revision: str = "f4f5b93cbb16"
down_revision: str | None = "45e411faf2e7"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None


def upgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###

    # Sync orgrole enum to uppercase BEFORE creating tables that use it
    # existing_server_default is what the default is BEFORE this migration runs
    op.sync_enum_values(  # type: ignore[attr-defined]
        enum_schema="public",
        enum_name="orgrole",
        new_values=["MEMBER", "ADMIN", "OWNER"],
        affected_columns=[
            TableReference(
                table_schema="public",
                table_name="organization_membership",
                column_name="role",
                existing_server_default="'member'::orgrole",
            )
        ],
        enum_values_to_rename=[
            ("member", "MEMBER"),
            ("admin", "ADMIN"),
            ("owner", "OWNER"),
        ],
    )

    sa.Enum("PENDING", "ACCEPTED", "REVOKED", name="invitationstatus").create(
        op.get_bind()
    )
    op.create_table(
        "organization_invitation",
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column("organization_id", sa.UUID(), nullable=False),
        sa.Column("email", sa.String(length=255), nullable=False),
        sa.Column(
            "role",
            postgresql.ENUM(
                "MEMBER", "ADMIN", "OWNER", name="orgrole", create_type=False
            ),
            nullable=False,
        ),
        sa.Column(
            "status",
            postgresql.ENUM(
                "PENDING",
                "ACCEPTED",
                "REVOKED",
                name="invitationstatus",
                create_type=False,
            ),
            nullable=False,
        ),
        sa.Column("invited_by", sa.UUID(), nullable=True),
        sa.Column("token", sa.String(length=64), nullable=False),
        sa.Column("expires_at", sa.TIMESTAMP(timezone=True), nullable=False),
        sa.Column("accepted_at", sa.TIMESTAMP(timezone=True), nullable=True),
        sa.Column(
            "created_at",
            sa.TIMESTAMP(timezone=True),
            server_default=sa.text("now()"),
            nullable=False,
        ),
        sa.Column(
            "updated_at",
            sa.TIMESTAMP(timezone=True),
            server_default=sa.text("now()"),
            nullable=False,
        ),
        sa.ForeignKeyConstraint(
            ["invited_by"],
            ["user.id"],
            name=op.f("fk_organization_invitation_invited_by_user"),
            ondelete="SET NULL",
        ),
        sa.ForeignKeyConstraint(
            ["organization_id"],
            ["organization.id"],
            name=op.f("fk_organization_invitation_organization_id_organization"),
            ondelete="CASCADE",
        ),
        sa.PrimaryKeyConstraint("id", name=op.f("pk_organization_invitation")),
        sa.UniqueConstraint("token", name=op.f("uq_organization_invitation_token")),
    )
    op.create_index(
        "ix_organization_invitation_email",
        "organization_invitation",
        ["email"],
        unique=False,
    )
    op.create_index(
        op.f("ix_organization_invitation_organization_id"),
        "organization_invitation",
        ["organization_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_organization_invitation_status"),
        "organization_invitation",
        ["status"],
        unique=False,
    )
    op.create_table(
        "invitation",
        sa.Column("id", sa.UUID(), nullable=False),
        sa.Column("workspace_id", sa.UUID(), nullable=False),
        sa.Column("email", sa.String(length=255), nullable=False),
        sa.Column(
            "role",
            postgresql.ENUM("EDITOR", "ADMIN", name="workspacerole", create_type=False),
            nullable=False,
        ),
        sa.Column(
            "status",
            postgresql.ENUM(
                "PENDING",
                "ACCEPTED",
                "REVOKED",
                name="invitationstatus",
                create_type=False,
            ),
            nullable=False,
        ),
        sa.Column("invited_by", sa.UUID(), nullable=True),
        sa.Column("token", sa.String(length=64), nullable=False),
        sa.Column("expires_at", sa.TIMESTAMP(timezone=True), nullable=False),
        sa.Column("accepted_at", sa.TIMESTAMP(timezone=True), nullable=True),
        sa.Column(
            "created_at",
            sa.TIMESTAMP(timezone=True),
            server_default=sa.text("now()"),
            nullable=False,
        ),
        sa.Column(
            "updated_at",
            sa.TIMESTAMP(timezone=True),
            server_default=sa.text("now()"),
            nullable=False,
        ),
        sa.ForeignKeyConstraint(
            ["invited_by"],
            ["user.id"],
            name=op.f("fk_invitation_invited_by_user"),
            ondelete="SET NULL",
        ),
        sa.ForeignKeyConstraint(
            ["workspace_id"],
            ["workspace.id"],
            name=op.f("fk_invitation_workspace_id_workspace"),
            ondelete="CASCADE",
        ),
        sa.PrimaryKeyConstraint("id", name=op.f("pk_invitation")),
        sa.UniqueConstraint("token", name=op.f("uq_invitation_token")),
    )
    op.create_index("ix_invitation_email", "invitation", ["email"], unique=False)
    op.create_index(
        op.f("ix_invitation_status"), "invitation", ["status"], unique=False
    )
    op.create_index(
        op.f("ix_invitation_workspace_id"), "invitation", ["workspace_id"], unique=False
    )
    # ### end Alembic commands ###


def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index(op.f("ix_invitation_workspace_id"), table_name="invitation")
    op.drop_index(op.f("ix_invitation_status"), table_name="invitation")
    op.drop_index("ix_invitation_email", table_name="invitation")
    op.drop_table("invitation")
    op.drop_index(
        op.f("ix_organization_invitation_status"), table_name="organization_invitation"
    )
    op.drop_index(
        op.f("ix_organization_invitation_organization_id"),
        table_name="organization_invitation",
    )
    op.drop_index(
        "ix_organization_invitation_email", table_name="organization_invitation"
    )
    op.drop_table("organization_invitation")
    sa.Enum("PENDING", "ACCEPTED", "REVOKED", name="invitationstatus").drop(
        op.get_bind()
    )

    # Sync orgrole enum back to lowercase AFTER dropping tables that use it
    # existing_server_default is 'MEMBER' (uppercase) after the upgrade ran
    op.sync_enum_values(  # type: ignore[attr-defined]
        enum_schema="public",
        enum_name="orgrole",
        new_values=["member", "admin", "owner"],
        affected_columns=[
            TableReference(
                table_schema="public",
                table_name="organization_membership",
                column_name="role",
                existing_server_default="'MEMBER'::orgrole",
            )
        ],
        enum_values_to_rename=[
            ("MEMBER", "member"),
            ("ADMIN", "admin"),
            ("OWNER", "owner"),
        ],
    )
    # ### end Alembic commands ###
