"""Worker Fleet: worker_fleet_registry, worker_fleet_events, worker_scaling_config.

Revision ID: 041
Revises: 040
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
from sqlalchemy.dialects.postgresql import ENUM as PgEnum

revision = "041"
down_revision = "040"
branch_labels = None
depends_on = None


def upgrade() -> None:
    op.execute("""
        DO $$ BEGIN
            CREATE TYPE p2hs_worker_type AS ENUM ('cf_worker', 'cf_queue_consumer');
        EXCEPTION WHEN duplicate_object THEN NULL;
        END $$
    """)
    op.execute("""
        DO $$ BEGIN
            CREATE TYPE p2hs_worker_status AS ENUM ('active', 'deploying', 'degraded', 'unhealthy', 'unknown');
        EXCEPTION WHEN duplicate_object THEN NULL;
        END $$
    """)
    op.execute("""
        DO $$ BEGIN
            CREATE TYPE p2hs_fleet_event_type AS ENUM (
                'deployed', 'scaled_up', 'scaled_down',
                'health_failed', 'recovered',
                'deploy_triggered', 'deploy_failed'
            );
        EXCEPTION WHEN duplicate_object THEN NULL;
        END $$
    """)

    op.create_table(
        "worker_fleet_registry",
        sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True),
        # pc-processor | pc-scheduler | pc-gateway | pc-realtime | pc-functions
        sa.Column("worker_name", sa.String(64), nullable=False),
        # supports multiple instances per worker type
        sa.Column("instance_id", sa.String(64), nullable=False),
        sa.Column(
            "worker_type",
            PgEnum(name="p2hs_worker_type", create_type=False),
            nullable=False,
        ),
        sa.Column("current_version", sa.String(64), nullable=True),
        sa.Column("target_version", sa.String(64), nullable=True),
        sa.Column(
            "status",
            PgEnum(name="p2hs_worker_status", create_type=False),
            nullable=False,
            server_default="unknown",
        ),
        # CF script / queue consumer identifiers
        sa.Column("cf_script_id", sa.String(128), nullable=True),
        sa.Column("cf_queue_consumer_id", sa.String(128), nullable=True),
        sa.Column("cf_queue_id", sa.String(128), nullable=True),
        # Concurrency — queue consumers only
        sa.Column("current_concurrency", sa.Integer, nullable=True),
        sa.Column("max_concurrency", sa.Integer, nullable=True, server_default="20"),
        sa.Column("min_concurrency", sa.Integer, nullable=True, server_default="1"),
        sa.Column("scale_up_threshold", sa.Integer, nullable=True),
        sa.Column("scale_down_threshold", sa.Integer, nullable=True),
        sa.Column("auto_deploy_enabled", sa.Boolean, nullable=False, server_default="false"),
        # Health
        sa.Column("health_url", sa.Text, nullable=True),
        sa.Column("last_health_check_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("last_health_check_ok", sa.Boolean, nullable=True),
        sa.Column("last_deployed_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.func.now()),
        sa.UniqueConstraint("worker_name", "instance_id", name="uq_fleet_worker_instance"),
    )
    op.create_index("ix_fleet_registry_worker_name", "worker_fleet_registry", ["worker_name"])

    op.create_table(
        "worker_fleet_events",
        sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True),
        sa.Column("worker_name", sa.String(64), nullable=False),
        sa.Column("instance_id", sa.String(64), nullable=False),
        sa.Column(
            "event_type",
            PgEnum(name="p2hs_fleet_event_type", create_type=False),
            nullable=False,
        ),
        sa.Column("from_value", sa.String(128), nullable=True),
        sa.Column("to_value", sa.String(128), nullable=True),
        # auto_scaler | admin | ci_webhook
        sa.Column("triggered_by", sa.String(32), nullable=False, server_default="auto_scaler"),
        sa.Column("occurred_at", sa.DateTime(timezone=True), server_default=sa.func.now()),
        sa.Column("metadata_json", postgresql.JSONB, nullable=True),
    )
    op.create_index("ix_fleet_events_worker_name", "worker_fleet_events", ["worker_name"])
    op.create_index("ix_fleet_events_occurred_at", "worker_fleet_events", ["occurred_at"])

    op.create_table(
        "worker_scaling_config",
        sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True),
        sa.Column("monitor_interval_seconds", sa.Integer, nullable=False, server_default="60"),
        sa.Column("auto_scale_enabled", sa.Boolean, nullable=False, server_default="true"),
        sa.Column("deployment_webhook_url", sa.Text, nullable=True),
        # Fernet-encrypted secret used to sign outbound CI webhook calls
        sa.Column("deployment_webhook_secret_enc", sa.Text, nullable=True),
        sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.func.now()),
    )


def downgrade() -> None:
    op.drop_table("worker_scaling_config")
    op.drop_table("worker_fleet_events")
    op.drop_table("worker_fleet_registry")
    op.execute("DROP TYPE IF EXISTS p2hs_fleet_event_type")
    op.execute("DROP TYPE IF EXISTS p2hs_worker_status")
    op.execute("DROP TYPE IF EXISTS p2hs_worker_type")
