"""Add Rule Engine tables (rules, rule_executions).

Revision ID: 44b803f122aa
Revises: 9e11fec12c10
Create Date: 2026-02-25 15:09:48.839431

"""

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 = "44b803f122aa"
down_revision: Union[str, None] = "9e11fec12c10"
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(
        "rules",
        sa.Column(
            "id", sa.UUID(), server_default=sa.text("gen_random_uuid()"), nullable=False
        ),
        sa.Column("tenant", sa.UUID(), nullable=False),
        sa.Column("name", sa.Text(), nullable=False),
        sa.Column("description", sa.Text(), nullable=True),
        sa.Column("source_device_id", sa.Text(), nullable=False),
        sa.Column(
            "source_metric", sa.Text(), server_default="numeric_value", nullable=False
        ),
        sa.Column("condition_operator", sa.Text(), nullable=False),
        sa.Column("condition_value", sa.Numeric(precision=15, scale=4), nullable=False),
        sa.Column(
            "condition_duration_seconds",
            sa.Integer(),
            server_default="0",
            nullable=False,
        ),
        sa.Column("hysteresis_value", sa.Numeric(precision=15, scale=4), nullable=True),
        sa.Column("target_device_id", sa.Text(), nullable=False),
        sa.Column("action", sa.Text(), nullable=False),
        sa.Column(
            "action_params",
            postgresql.JSONB(astext_type=sa.Text()),
            server_default="{}",
            nullable=False,
        ),
        sa.Column(
            "cooldown_seconds", sa.Integer(), server_default="300", nullable=False
        ),
        sa.Column("max_executions_per_day", sa.Integer(), nullable=True),
        sa.Column("priority", sa.Integer(), server_default="0", nullable=False),
        sa.Column("is_active", sa.Boolean(), server_default="true", nullable=False),
        sa.Column("last_triggered_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("last_condition_true_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("executions_today", sa.Integer(), server_default="0", nullable=False),
        sa.Column(
            "created_at",
            sa.DateTime(timezone=True),
            server_default=sa.text("NOW()"),
            nullable=False,
        ),
        sa.Column(
            "updated_at",
            sa.DateTime(timezone=True),
            server_default=sa.text("NOW()"),
            nullable=False,
        ),
        sa.Column("created_by", sa.Text(), nullable=True),
        sa.CheckConstraint(
            "condition_operator IN ('>', '<', '>=', '<=', '==', '!=')",
            name="chk_rules_condition_operator",
        ),
        sa.CheckConstraint(
            "condition_duration_seconds >= 0", name="chk_rules_duration_positive"
        ),
        sa.CheckConstraint("cooldown_seconds >= 0", name="chk_rules_cooldown_positive"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        "idx_rules_is_active",
        "rules",
        ["is_active"],
        unique=False,
        postgresql_where="is_active = TRUE",
    )
    op.create_index(
        "idx_rules_tenant_active",
        "rules",
        ["tenant", "is_active"],
        unique=False,
        postgresql_where="is_active = TRUE",
    )
    op.create_index(
        op.f("ix_rules_source_device_id"), "rules", ["source_device_id"], unique=False
    )
    op.create_index(
        op.f("ix_rules_target_device_id"), "rules", ["target_device_id"], unique=False
    )
    op.create_index(op.f("ix_rules_tenant"), "rules", ["tenant"], unique=False)
    op.create_table(
        "rule_executions",
        sa.Column(
            "id", sa.UUID(), server_default=sa.text("gen_random_uuid()"), nullable=False
        ),
        sa.Column("rule_id", sa.UUID(), nullable=False),
        sa.Column("tenant", sa.UUID(), nullable=False),
        sa.Column("triggered_value", sa.Numeric(precision=15, scale=4), nullable=False),
        sa.Column("threshold_value", sa.Numeric(precision=15, scale=4), nullable=False),
        sa.Column("status", sa.Text(), nullable=False),
        sa.Column("command_id", sa.UUID(), nullable=True),
        sa.Column("error_message", sa.Text(), nullable=True),
        sa.Column(
            "evaluated_at",
            sa.DateTime(timezone=True),
            server_default=sa.text("NOW()"),
            nullable=False,
        ),
        sa.Column("condition_true_since", sa.DateTime(timezone=True), nullable=True),
        sa.Column(
            "created_at",
            sa.DateTime(timezone=True),
            server_default=sa.text("NOW()"),
            nullable=False,
        ),
        sa.ForeignKeyConstraint(["rule_id"], ["rules.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        "idx_rule_executions_command_id",
        "rule_executions",
        ["command_id"],
        unique=False,
        postgresql_where="command_id IS NOT NULL",
    )
    op.create_index(
        "idx_rule_executions_created_at",
        "rule_executions",
        ["created_at"],
        unique=False,
    )
    op.create_index(
        "idx_rule_executions_status", "rule_executions", ["status"], unique=False
    )
    op.create_index(
        op.f("ix_rule_executions_rule_id"), "rule_executions", ["rule_id"], unique=False
    )
    op.create_index(
        op.f("ix_rule_executions_tenant"), "rule_executions", ["tenant"], unique=False
    )
    # ### end Alembic commands ###


def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index(op.f("ix_rule_executions_tenant"), table_name="rule_executions")
    op.drop_index(op.f("ix_rule_executions_rule_id"), table_name="rule_executions")
    op.drop_index("idx_rule_executions_status", table_name="rule_executions")
    op.drop_index("idx_rule_executions_created_at", table_name="rule_executions")
    op.drop_index(
        "idx_rule_executions_command_id",
        table_name="rule_executions",
        postgresql_where="command_id IS NOT NULL",
    )
    op.drop_table("rule_executions")
    op.drop_index(op.f("ix_rules_tenant"), table_name="rules")
    op.drop_index(op.f("ix_rules_target_device_id"), table_name="rules")
    op.drop_index(op.f("ix_rules_source_device_id"), table_name="rules")
    op.drop_index(
        "idx_rules_tenant_active",
        table_name="rules",
        postgresql_where="is_active = TRUE",
    )
    op.drop_index(
        "idx_rules_is_active", table_name="rules", postgresql_where="is_active = TRUE"
    )
    op.drop_table("rules")
    # ### end Alembic commands ###
