"""Virtual Boxes e Notifiche Multi-canale – Fase 2

Revision ID: 0003
Revises: 0002
Create Date: 2026-03-19 00:00:00.000000

Aggiunge le tabelle:
  - virtual_boxes
  - virtual_box_rules
  - virtual_box_assignments
  - notification_channels  (+ ENUM notification_channel_type)
  - notification_rules
  - notification_log        (+ ENUM notification_status)
"""

from alembic import op

revision = "0003"
down_revision = "0002"
branch_labels = None
depends_on = None


def upgrade() -> None:
    # ── ENUM types ────────────────────────────────────────────────────────────
    op.execute(
        "CREATE TYPE notification_channel_type AS ENUM "
        "('webhook', 'email', 'telegram', 'whatsapp')"
    )
    op.execute(
        "CREATE TYPE notification_status AS ENUM "
        "('pending', 'sent', 'failed', 'skipped')"
    )

    # ── VIRTUAL BOXES ─────────────────────────────────────────────────────────
    op.execute("""
        CREATE TABLE virtual_boxes (
            id          UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
            tenant_id   UUID         NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
            name        VARCHAR(255) NOT NULL,
            description TEXT,
            label       VARCHAR(100),
            is_active   BOOLEAN      NOT NULL DEFAULT TRUE,
            created_by  UUID         REFERENCES users(id),
            created_at  TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
            updated_at  TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
            CONSTRAINT uq_vbox_name_tenant UNIQUE (tenant_id, name)
        )
    """)
    op.execute("CREATE INDEX idx_vbox_tenant ON virtual_boxes (tenant_id)")
    op.execute("""
        CREATE TRIGGER trg_virtual_boxes_updated_at
        BEFORE UPDATE ON virtual_boxes
        FOR EACH ROW EXECUTE FUNCTION set_updated_at()
    """)

    op.execute("""
        CREATE TABLE virtual_box_rules (
            id              UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
            virtual_box_id  UUID         NOT NULL REFERENCES virtual_boxes(id) ON DELETE CASCADE,
            field           VARCHAR(50)  NOT NULL,
            operator        VARCHAR(20)  NOT NULL DEFAULT 'contains',
            value           TEXT         NOT NULL,
            date_from       VARCHAR(20),
            date_to         VARCHAR(20),
            created_at      TIMESTAMPTZ  NOT NULL DEFAULT NOW()
        )
    """)
    op.execute("CREATE INDEX idx_vbox_rule_vbox ON virtual_box_rules (virtual_box_id)")

    op.execute("""
        CREATE TABLE virtual_box_assignments (
            id              UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
            virtual_box_id  UUID NOT NULL REFERENCES virtual_boxes(id) ON DELETE CASCADE,
            user_id         UUID NOT NULL REFERENCES users(id)         ON DELETE CASCADE,
            assigned_by     UUID REFERENCES users(id),
            assigned_at     TIMESTAMPTZ NOT NULL DEFAULT NOW(),
            CONSTRAINT uq_vbox_assignment UNIQUE (virtual_box_id, user_id)
        )
    """)
    op.execute("CREATE INDEX idx_vbox_assign_user ON virtual_box_assignments (user_id)")
    op.execute("CREATE INDEX idx_vbox_assign_vbox ON virtual_box_assignments (virtual_box_id)")

    # ── NOTIFICATION CHANNELS ─────────────────────────────────────────────────
    op.execute("""
        CREATE TABLE notification_channels (
            id                      UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
            tenant_id               UUID                       NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
            name                    VARCHAR(255)               NOT NULL,
            channel_type            notification_channel_type  NOT NULL,
            is_active               BOOLEAN                    NOT NULL DEFAULT TRUE,
            config                  JSONB,
            config_enc              TEXT,
            consecutive_failures    INT                        NOT NULL DEFAULT 0,
            circuit_open_until      TIMESTAMPTZ,
            created_by              UUID REFERENCES users(id),
            created_at              TIMESTAMPTZ NOT NULL DEFAULT NOW(),
            updated_at              TIMESTAMPTZ NOT NULL DEFAULT NOW()
        )
    """)
    op.execute("CREATE INDEX idx_notif_channel_tenant ON notification_channels (tenant_id)")
    op.execute("""
        CREATE TRIGGER trg_notification_channels_updated_at
        BEFORE UPDATE ON notification_channels
        FOR EACH ROW EXECUTE FUNCTION set_updated_at()
    """)

    op.execute("""
        CREATE TABLE notification_rules (
            id          UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
            tenant_id   UUID         NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
            channel_id  UUID         NOT NULL REFERENCES notification_channels(id) ON DELETE CASCADE,
            name        VARCHAR(255) NOT NULL,
            event_type  VARCHAR(100) NOT NULL,
            filter      JSONB,
            is_active   BOOLEAN      NOT NULL DEFAULT TRUE,
            created_at  TIMESTAMPTZ  NOT NULL DEFAULT NOW()
        )
    """)
    op.execute("CREATE INDEX idx_notif_rule_tenant  ON notification_rules (tenant_id)")
    op.execute("CREATE INDEX idx_notif_rule_channel ON notification_rules (channel_id)")
    op.execute("CREATE INDEX idx_notif_rule_event   ON notification_rules (event_type)")

    op.execute("""
        CREATE TABLE notification_log (
            id              UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
            tenant_id       UUID                NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
            channel_id      UUID                NOT NULL REFERENCES notification_channels(id) ON DELETE CASCADE,
            rule_id         UUID                REFERENCES notification_rules(id) ON DELETE SET NULL,
            event_type      VARCHAR(100)        NOT NULL,
            event_payload   JSONB,
            status          notification_status NOT NULL DEFAULT 'pending',
            attempt_count   INT                 NOT NULL DEFAULT 0,
            max_attempts    INT                 NOT NULL DEFAULT 3,
            next_retry_at   TIMESTAMPTZ,
            last_error      TEXT,
            http_status     INT,
            sent_at         TIMESTAMPTZ,
            created_at      TIMESTAMPTZ         NOT NULL DEFAULT NOW()
        )
    """)
    op.execute("CREATE INDEX idx_notif_log_tenant  ON notification_log (tenant_id)")
    op.execute("CREATE INDEX idx_notif_log_channel ON notification_log (channel_id)")
    op.execute(
        "CREATE INDEX idx_notif_log_status ON notification_log (status, next_retry_at) "
        "WHERE status IN ('pending', 'failed')"
    )


def downgrade() -> None:
    for table in [
        "notification_log",
        "notification_rules",
        "notification_channels",
        "virtual_box_assignments",
        "virtual_box_rules",
        "virtual_boxes",
    ]:
        op.execute(f"DROP TABLE IF EXISTS {table} CASCADE")

    op.execute("DROP TYPE IF EXISTS notification_status")
    op.execute("DROP TYPE IF EXISTS notification_channel_type")
