"""Add Command API models

Revision ID: 9e11fec12c10
Revises: 9636e66fc187
Create Date: 2026-02-23 14:21:45.873591

"""

from typing import Sequence, Union

import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

from alembic import op

# revision identifiers, used by Alembic.
revision: str = "9e11fec12c10"
down_revision: Union[str, None] = "9636e66fc187"
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(
        "command_device_mapping",
        sa.Column("id", sa.Integer(), autoincrement=True, nullable=False),
        sa.Column("tenant", sa.UUID(), nullable=False),
        sa.Column("device_id", sa.Text(), nullable=False),
        sa.Column("platform", sa.Text(), nullable=False),
        sa.Column("platform_device_id", sa.Text(), nullable=False),
        sa.Column(
            "platform_config",
            postgresql.JSONB(astext_type=sa.Text()),
            server_default="{}",
            nullable=False,
        ),
        sa.Column("supported_actions", postgresql.ARRAY(sa.Text()), nullable=False),
        sa.Column("is_active", sa.Boolean(), server_default="true", nullable=False),
        sa.Column(
            "created_at",
            sa.DateTime(timezone=True),
            server_default="NOW()",
            nullable=False,
        ),
        sa.Column(
            "updated_at",
            sa.DateTime(timezone=True),
            server_default="NOW()",
            nullable=False,
        ),
        sa.PrimaryKeyConstraint("id"),
        sa.UniqueConstraint(
            "tenant",
            "device_id",
            "platform",
            name="uq_cmd_device_mapping_tenant_device_platform",
        ),
    )
    op.create_index(
        "idx_cmd_device_mapping_lookup",
        "command_device_mapping",
        ["tenant", "device_id"],
        unique=False,
        postgresql_where="is_active = true",
    )
    op.create_index(
        op.f("ix_command_device_mapping_tenant"),
        "command_device_mapping",
        ["tenant"],
        unique=False,
    )
    op.create_table(
        "command_log",
        sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
        sa.Column("command_id", sa.UUID(), nullable=False),
        sa.Column("tenant", sa.UUID(), nullable=False),
        sa.Column("device_id", sa.Text(), nullable=False),
        sa.Column("platform", sa.Text(), nullable=False),
        sa.Column("platform_device_id", sa.Text(), nullable=False),
        sa.Column("action", sa.Text(), nullable=False),
        sa.Column("params", postgresql.JSONB(astext_type=sa.Text()), nullable=True),
        sa.Column("event_type", sa.Text(), nullable=False),
        sa.Column("event_data", postgresql.JSONB(astext_type=sa.Text()), nullable=True),
        sa.Column("created_by", sa.Text(), nullable=False),
        sa.Column(
            "created_at",
            sa.DateTime(timezone=True),
            server_default="NOW()",
            nullable=False,
        ),
        sa.Column("execution_time_ms", sa.Integer(), nullable=True),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        "idx_command_log_command", "command_log", ["command_id"], unique=False
    )
    op.create_index(
        "idx_command_log_device",
        "command_log",
        ["device_id", "created_at"],
        unique=False,
    )
    op.create_index(
        "idx_command_log_tenant", "command_log", ["tenant", "created_at"], unique=False
    )
    op.create_index(
        op.f("ix_command_log_command_id"), "command_log", ["command_id"], unique=False
    )
    op.create_table(
        "command_queue",
        sa.Column(
            "id", sa.UUID(), server_default=sa.text("gen_random_uuid()"), nullable=False
        ),
        sa.Column("tenant", sa.UUID(), nullable=False),
        sa.Column("device_id", sa.Text(), nullable=False),
        sa.Column("platform", sa.Text(), nullable=False),
        sa.Column("platform_device_id", sa.Text(), nullable=False),
        sa.Column("action", sa.Text(), nullable=False),
        sa.Column(
            "params",
            postgresql.JSONB(astext_type=sa.Text()),
            server_default="{}",
            nullable=False,
        ),
        sa.Column("status", sa.Text(), server_default="pending", nullable=False),
        sa.Column("priority", sa.Integer(), server_default="0", nullable=False),
        sa.Column("attempt_count", sa.Integer(), server_default="0", nullable=False),
        sa.Column("max_attempts", sa.Integer(), server_default="3", nullable=False),
        sa.Column("next_retry_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("created_by", sa.Text(), nullable=False),
        sa.Column(
            "created_at",
            sa.DateTime(timezone=True),
            server_default="NOW()",
            nullable=False,
        ),
        sa.Column(
            "updated_at",
            sa.DateTime(timezone=True),
            server_default="NOW()",
            nullable=False,
        ),
        sa.Column("locked_by", sa.Text(), nullable=True),
        sa.Column("locked_at", sa.DateTime(timezone=True), nullable=True),
        sa.CheckConstraint(
            "platform IN ('supla', 'chirpstack')", name="valid_platform"
        ),
        sa.CheckConstraint(
            "status IN ('pending', 'processing', 'completed', 'failed', 'cancelled')",
            name="valid_status",
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        "idx_command_queue_device",
        "command_queue",
        ["device_id", "created_at"],
        unique=False,
    )
    op.create_index(
        "idx_command_queue_locked",
        "command_queue",
        ["locked_at"],
        unique=False,
        postgresql_where="locked_by IS NOT NULL",
    )
    op.create_index(
        "idx_command_queue_pending",
        "command_queue",
        ["priority", "created_at"],
        unique=False,
        postgresql_where="status = 'pending'",
    )
    op.create_index(
        "idx_command_queue_tenant",
        "command_queue",
        ["tenant", "created_at"],
        unique=False,
    )
    op.create_index(
        op.f("ix_command_queue_device_id"), "command_queue", ["device_id"], unique=False
    )
    op.create_index(
        op.f("ix_command_queue_tenant"), "command_queue", ["tenant"], unique=False
    )
    # ### end Alembic commands ###


def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index(op.f("ix_command_queue_tenant"), table_name="command_queue")
    op.drop_index(op.f("ix_command_queue_device_id"), table_name="command_queue")
    op.drop_index("idx_command_queue_tenant", table_name="command_queue")
    op.drop_index(
        "idx_command_queue_pending",
        table_name="command_queue",
        postgresql_where="status = 'pending'",
    )
    op.drop_index(
        "idx_command_queue_locked",
        table_name="command_queue",
        postgresql_where="locked_by IS NOT NULL",
    )
    op.drop_index("idx_command_queue_device", table_name="command_queue")
    op.drop_table("command_queue")
    op.drop_index(op.f("ix_command_log_command_id"), table_name="command_log")
    op.drop_index("idx_command_log_tenant", table_name="command_log")
    op.drop_index("idx_command_log_device", table_name="command_log")
    op.drop_index("idx_command_log_command", table_name="command_log")
    op.drop_table("command_log")
    op.drop_index(
        op.f("ix_command_device_mapping_tenant"), table_name="command_device_mapping"
    )
    op.drop_index(
        "idx_cmd_device_mapping_lookup",
        table_name="command_device_mapping",
        postgresql_where="is_active = true",
    )
    op.drop_table("command_device_mapping")
    # ### end Alembic commands ###
