"""Add monitoring models (CostSnapshot, CronJobStatus, SessionEvent, SubAgentRun, SystemHealthMetric, AlertRule, AlertEvent).

Revision ID: 7a8b9c0d1e2f
Revises: f4d2b649e93a
Create Date: 2026-05-10 00:00:00.000000

"""

from __future__ import annotations

import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision = "7a8b9c0d1e2f"
down_revision = "a9b1c2d3e4f7"
branch_labels = None
depends_on = None


def upgrade() -> None:
    """Create monitoring tables."""
    _upgrade_monitoring_tables()


def _upgrade_monitoring_tables() -> None:
    # cost_snapshots
    op.create_table(
        "cost_snapshots",
        sa.Column("id", sa.Uuid(), nullable=False),
        sa.Column("organization_id", sa.Uuid(), nullable=False),
        sa.Column("gateway_id", sa.Uuid(), nullable=False),
        sa.Column("period_start", sa.DateTime(), nullable=False),
        sa.Column("period_end", sa.DateTime(), nullable=False),
        sa.Column("total_cost", sa.Float(), nullable=False),
        sa.Column("model_costs", sa.JSON(), nullable=True),
        sa.Column("provider_costs", sa.JSON(), nullable=True),
        sa.Column("token_counts", sa.JSON(), nullable=True),
        sa.Column("collected_at", sa.DateTime(), nullable=False),
        sa.Column("created_at", sa.DateTime(), nullable=False),
        sa.Column("updated_at", sa.DateTime(), nullable=False),
        sa.ForeignKeyConstraint(["organization_id"], ["organizations.id"], ondelete="CASCADE"),
        sa.ForeignKeyConstraint(["gateway_id"], ["gateways.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_cost_snapshots_organization_id"),
        "cost_snapshots",
        ["organization_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_cost_snapshots_gateway_id"),
        "cost_snapshots",
        ["gateway_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_cost_snapshots_org_created"),
        "cost_snapshots",
        ["organization_id", "created_at"],
        unique=False,
    )
    op.create_index(
        op.f("ix_cost_snapshots_org_gateway"),
        "cost_snapshots",
        ["organization_id", "gateway_id"],
        unique=False,
    )

    # cron_job_statuses
    op.create_table(
        "cron_job_statuses",
        sa.Column("id", sa.Uuid(), nullable=False),
        sa.Column("organization_id", sa.Uuid(), nullable=False),
        sa.Column("gateway_id", sa.Uuid(), nullable=False),
        sa.Column("job_name", sa.String(), nullable=False),
        sa.Column("schedule", sa.String(), nullable=False),
        sa.Column("enabled", sa.Boolean(), nullable=True),
        sa.Column("last_run_at", sa.DateTime(), nullable=True),
        sa.Column("next_run_at", sa.DateTime(), nullable=True),
        sa.Column("status", sa.String(), nullable=False),
        sa.Column("failure_count", sa.Integer(), nullable=False),
        sa.Column("last_error", sa.String(), nullable=True),
        sa.Column("metadata_", sa.JSON(), nullable=True),
        sa.Column("created_at", sa.DateTime(), nullable=False),
        sa.Column("updated_at", sa.DateTime(), nullable=False),
        sa.ForeignKeyConstraint(["organization_id"], ["organizations.id"], ondelete="CASCADE"),
        sa.ForeignKeyConstraint(["gateway_id"], ["gateways.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_cron_job_statuses_organization_id"),
        "cron_job_statuses",
        ["organization_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_cron_job_statuses_gateway_id"),
        "cron_job_statuses",
        ["gateway_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_cron_job_statuses_job_name"),
        "cron_job_statuses",
        ["job_name"],
        unique=False,
    )
    op.create_index(
        op.f("ix_cron_job_statuses_org_created"),
        "cron_job_statuses",
        ["organization_id", "created_at"],
        unique=False,
    )
    op.create_index(
        op.f("ix_cron_job_statuses_org_gateway"),
        "cron_job_statuses",
        ["organization_id", "gateway_id"],
        unique=False,
    )

    # session_events
    op.create_table(
        "session_events",
        sa.Column("id", sa.Uuid(), nullable=False),
        sa.Column("organization_id", sa.Uuid(), nullable=False),
        sa.Column("gateway_id", sa.Uuid(), nullable=False),
        sa.Column("session_key", sa.String(), nullable=False),
        sa.Column("event_type", sa.String(), nullable=False),
        sa.Column("model", sa.String(), nullable=True),
        sa.Column("agent_id", sa.String(), nullable=True),
        sa.Column("channel", sa.String(), nullable=True),
        sa.Column("context_percent", sa.Float(), nullable=True),
        sa.Column("token_counts", sa.JSON(), nullable=True),
        sa.Column("cost", sa.Float(), nullable=True),
        sa.Column("metadata_", sa.JSON(), nullable=True),
        sa.Column("created_at", sa.DateTime(), nullable=False),
        sa.Column("updated_at", sa.DateTime(), nullable=False),
        sa.ForeignKeyConstraint(["organization_id"], ["organizations.id"], ondelete="CASCADE"),
        sa.ForeignKeyConstraint(["gateway_id"], ["gateways.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_session_events_organization_id"),
        "session_events",
        ["organization_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_session_events_gateway_id"),
        "session_events",
        ["gateway_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_session_events_session_key"),
        "session_events",
        ["session_key"],
        unique=False,
    )
    op.create_index(
        op.f("ix_session_events_org_created"),
        "session_events",
        ["organization_id", "created_at"],
        unique=False,
    )
    op.create_index(
        op.f("ix_session_events_org_gateway"),
        "session_events",
        ["organization_id", "gateway_id"],
        unique=False,
    )

    # sub_agent_runs
    op.create_table(
        "sub_agent_runs",
        sa.Column("id", sa.Uuid(), nullable=False),
        sa.Column("organization_id", sa.Uuid(), nullable=False),
        sa.Column("gateway_id", sa.Uuid(), nullable=False),
        sa.Column("parent_session_key", sa.String(), nullable=False),
        sa.Column("session_event_id", sa.Uuid(), nullable=True),
        sa.Column("agent", sa.String(), nullable=True),
        sa.Column("model", sa.String(), nullable=True),
        sa.Column("status", sa.String(), nullable=False),
        sa.Column("duration_ms", sa.Integer(), nullable=True),
        sa.Column("cost", sa.Float(), nullable=True),
        sa.Column("token_counts", sa.JSON(), nullable=True),
        sa.Column("metadata_", sa.JSON(), nullable=True),
        sa.Column("created_at", sa.DateTime(), nullable=False),
        sa.Column("updated_at", sa.DateTime(), nullable=False),
        sa.ForeignKeyConstraint(["organization_id"], ["organizations.id"], ondelete="CASCADE"),
        sa.ForeignKeyConstraint(["gateway_id"], ["gateways.id"], ondelete="CASCADE"),
        sa.ForeignKeyConstraint(["session_event_id"], ["session_events.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_sub_agent_runs_organization_id"),
        "sub_agent_runs",
        ["organization_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_sub_agent_runs_gateway_id"),
        "sub_agent_runs",
        ["gateway_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_sub_agent_runs_parent_session_key"),
        "sub_agent_runs",
        ["parent_session_key"],
        unique=False,
    )
    op.create_index(
        op.f("ix_sub_agent_runs_session_event_id"),
        "sub_agent_runs",
        ["session_event_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_sub_agent_runs_org_created"),
        "sub_agent_runs",
        ["organization_id", "created_at"],
        unique=False,
    )
    op.create_index(
        op.f("ix_sub_agent_runs_org_gateway"),
        "sub_agent_runs",
        ["organization_id", "gateway_id"],
        unique=False,
    )

    # system_health_metrics
    op.create_table(
        "system_health_metrics",
        sa.Column("id", sa.Uuid(), nullable=False),
        sa.Column("organization_id", sa.Uuid(), nullable=False),
        sa.Column("gateway_id", sa.Uuid(), nullable=False),
        sa.Column("cpu_percent", sa.Float(), nullable=True),
        sa.Column("cpu_cores", sa.Integer(), nullable=True),
        sa.Column("ram_used_bytes", sa.Integer(), nullable=True),
        sa.Column("ram_total_bytes", sa.Integer(), nullable=True),
        sa.Column("ram_percent", sa.Float(), nullable=True),
        sa.Column("swap_used_bytes", sa.Integer(), nullable=True),
        sa.Column("swap_total_bytes", sa.Integer(), nullable=True),
        sa.Column("swap_percent", sa.Float(), nullable=True),
        sa.Column("disk_path", sa.String(), nullable=False),
        sa.Column("disk_used_bytes", sa.Integer(), nullable=True),
        sa.Column("disk_total_bytes", sa.Integer(), nullable=True),
        sa.Column("disk_percent", sa.Float(), nullable=True),
        sa.Column("gateway_live", sa.Boolean(), nullable=True),
        sa.Column("gateway_ready", sa.Boolean(), nullable=True),
        sa.Column("gateway_uptime_ms", sa.Integer(), nullable=True),
        sa.Column("gateway_pid", sa.Integer(), nullable=True),
        sa.Column("gateway_version", sa.String(), nullable=True),
        sa.Column("metadata_", sa.JSON(), nullable=True),
        sa.Column("collected_at", sa.DateTime(), nullable=False),
        sa.Column("created_at", sa.DateTime(), nullable=False),
        sa.Column("updated_at", sa.DateTime(), nullable=False),
        sa.ForeignKeyConstraint(["organization_id"], ["organizations.id"], ondelete="CASCADE"),
        sa.ForeignKeyConstraint(["gateway_id"], ["gateways.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_system_health_metrics_organization_id"),
        "system_health_metrics",
        ["organization_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_system_health_metrics_gateway_id"),
        "system_health_metrics",
        ["gateway_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_system_health_metrics_org_created"),
        "system_health_metrics",
        ["organization_id", "created_at"],
        unique=False,
    )
    op.create_index(
        op.f("ix_system_health_metrics_org_gateway"),
        "system_health_metrics",
        ["organization_id", "gateway_id"],
        unique=False,
    )

    # alert_rules
    op.create_table(
        "alert_rules",
        sa.Column("id", sa.Uuid(), nullable=False),
        sa.Column("organization_id", sa.Uuid(), nullable=False),
        sa.Column("name", sa.String(), nullable=False),
        sa.Column("metric_type", sa.String(), nullable=False),
        sa.Column("threshold", sa.Float(), nullable=False),
        sa.Column("comparison", sa.String(), nullable=False),
        sa.Column("enabled", sa.Boolean(), nullable=True),
        sa.Column("cooldown_minutes", sa.Integer(), nullable=False),
        sa.Column("description", sa.String(), nullable=True),
        sa.Column("metadata_", sa.JSON(), nullable=True),
        sa.Column("created_at", sa.DateTime(), nullable=False),
        sa.Column("updated_at", sa.DateTime(), nullable=False),
        sa.ForeignKeyConstraint(["organization_id"], ["organizations.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_alert_rules_organization_id"),
        "alert_rules",
        ["organization_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_alert_rules_metric_type"),
        "alert_rules",
        ["metric_type"],
        unique=False,
    )
    op.create_index(
        op.f("ix_alert_rules_org_created"),
        "alert_rules",
        ["organization_id", "created_at"],
        unique=False,
    )
    op.create_index(
        op.f("ix_alert_rules_org_gateway"),
        "alert_rules",
        ["organization_id", "gateway_id"],
        unique=False,
    )

    # alert_events
    op.create_table(
        "alert_events",
        sa.Column("id", sa.Uuid(), nullable=False),
        sa.Column("organization_id", sa.Uuid(), nullable=False),
        sa.Column("rule_id", sa.Uuid(), nullable=False),
        sa.Column("gateway_id", sa.Uuid(), nullable=True),
        sa.Column("metric_type", sa.String(), nullable=False),
        sa.Column("triggered_value", sa.Float(), nullable=False),
        sa.Column("threshold_value", sa.Float(), nullable=False),
        sa.Column("acknowledged", sa.Boolean(), nullable=False),
        sa.Column("acknowledged_at", sa.DateTime(), nullable=True),
        sa.Column("acknowledged_by", sa.Uuid(), nullable=True),
        sa.Column("resolved_at", sa.DateTime(), nullable=True),
        sa.Column("metadata_", sa.JSON(), nullable=True),
        sa.Column("created_at", sa.DateTime(), nullable=False),
        sa.Column("updated_at", sa.DateTime(), nullable=False),
        sa.ForeignKeyConstraint(["organization_id"], ["organizations.id"], ondelete="CASCADE"),
        sa.ForeignKeyConstraint(["rule_id"], ["alert_rules.id"], ondelete="CASCADE"),
        sa.ForeignKeyConstraint(["gateway_id"], ["gateways.id"], ondelete="CASCADE"),
        sa.ForeignKeyConstraint(["acknowledged_by"], ["users.id"], ondelete="SET NULL"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index(
        op.f("ix_alert_events_organization_id"),
        "alert_events",
        ["organization_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_alert_events_rule_id"),
        "alert_events",
        ["rule_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_alert_events_gateway_id"),
        "alert_events",
        ["gateway_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_alert_events_metric_type"),
        "alert_events",
        ["metric_type"],
        unique=False,
    )
    op.create_index(
        op.f("ix_alert_events_org_created"),
        "alert_events",
        ["organization_id", "created_at"],
        unique=False,
    )
    op.create_index(
        op.f("ix_alert_events_org_gateway"),
        "alert_events",
        ["organization_id", "gateway_id"],
        unique=False,
    )
    op.create_index(
        op.f("ix_alert_events_rule_created"),
        "alert_events",
        ["rule_id", "created_at"],
        unique=False,
    )


def downgrade() -> None:
    """Drop monitoring tables."""
    op.drop_index(op.f("ix_alert_events_rule_created"), table_name="alert_events")
    op.drop_index(op.f("ix_alert_events_org_gateway"), table_name="alert_events")
    op.drop_index(op.f("ix_alert_events_org_created"), table_name="alert_events")
    op.drop_index(op.f("ix_alert_events_metric_type"), table_name="alert_events")
    op.drop_index(op.f("ix_alert_events_gateway_id"), table_name="alert_events")
    op.drop_index(op.f("ix_alert_events_rule_id"), table_name="alert_events")
    op.drop_index(op.f("ix_alert_events_organization_id"), table_name="alert_events")
    op.drop_table("alert_events")

    op.drop_index(op.f("ix_alert_rules_org_gateway"), table_name="alert_rules")
    op.drop_index(op.f("ix_alert_rules_org_created"), table_name="alert_rules")
    op.drop_index(op.f("ix_alert_rules_metric_type"), table_name="alert_rules")
    op.drop_index(op.f("ix_alert_rules_organization_id"), table_name="alert_rules")
    op.drop_table("alert_rules")

    op.drop_index(op.f("ix_system_health_metrics_org_gateway"), table_name="system_health_metrics")
    op.drop_index(op.f("ix_system_health_metrics_org_created"), table_name="system_health_metrics")
    op.drop_index(op.f("ix_system_health_metrics_gateway_id"), table_name="system_health_metrics")
    op.drop_index(op.f("ix_system_health_metrics_organization_id"), table_name="system_health_metrics")
    op.drop_table("system_health_metrics")

    op.drop_index(op.f("ix_sub_agent_runs_org_gateway"), table_name="sub_agent_runs")
    op.drop_index(op.f("ix_sub_agent_runs_org_created"), table_name="sub_agent_runs")
    op.drop_index(op.f("ix_sub_agent_runs_session_event_id"), table_name="sub_agent_runs")
    op.drop_index(op.f("ix_sub_agent_runs_parent_session_key"), table_name="sub_agent_runs")
    op.drop_index(op.f("ix_sub_agent_runs_gateway_id"), table_name="sub_agent_runs")
    op.drop_index(op.f("ix_sub_agent_runs_organization_id"), table_name="sub_agent_runs")
    op.drop_table("sub_agent_runs")

    op.drop_index(op.f("ix_session_events_org_gateway"), table_name="session_events")
    op.drop_index(op.f("ix_session_events_org_created"), table_name="session_events")
    op.drop_index(op.f("ix_session_events_session_key"), table_name="session_events")
    op.drop_index(op.f("ix_session_events_gateway_id"), table_name="session_events")
    op.drop_index(op.f("ix_session_events_organization_id"), table_name="session_events")
    op.drop_table("session_events")

    op.drop_index(op.f("ix_cron_job_statuses_org_gateway"), table_name="cron_job_statuses")
    op.drop_index(op.f("ix_cron_job_statuses_org_created"), table_name="cron_job_statuses")
    op.drop_index(op.f("ix_cron_job_statuses_job_name"), table_name="cron_job_statuses")
    op.drop_index(op.f("ix_cron_job_statuses_gateway_id"), table_name="cron_job_statuses")
    op.drop_index(op.f("ix_cron_job_statuses_organization_id"), table_name="cron_job_statuses")
    op.drop_table("cron_job_statuses")

    op.drop_index(op.f("ix_cost_snapshots_org_gateway"), table_name="cost_snapshots")
    op.drop_index(op.f("ix_cost_snapshots_org_created"), table_name="cost_snapshots")
    op.drop_index(op.f("ix_cost_snapshots_gateway_id"), table_name="cost_snapshots")
    op.drop_index(op.f("ix_cost_snapshots_organization_id"), table_name="cost_snapshots")
    op.drop_table("cost_snapshots")
