"""add fediverse social tables

Revision ID: l2j0g6h8i9
Revises: k1i9f5g7h8
Create Date: 2026-02-22

Creates:
- ap_remote_actors    — cached profiles of remote actors
- ap_following        — outbound follows (local → remote)
- ap_remote_posts     — ingested posts from remote actors
- ap_local_posts      — native posts composed in federation UI
- ap_interactions     — likes and boosts
- ap_notifications    — follow/like/boost/mention/reply notifications
"""

from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects.postgresql import JSONB

revision = "l2j0g6h8i9"
down_revision = "k1i9f5g7h8"
branch_labels = None
depends_on = None


def upgrade() -> None:
    # -- ap_remote_actors --
    op.create_table(
        "ap_remote_actors",
        sa.Column("id", sa.Integer, primary_key=True, autoincrement=True),
        sa.Column("actor_url", sa.String(512), unique=True, nullable=False),
        sa.Column("inbox_url", sa.String(512), nullable=False),
        sa.Column("shared_inbox_url", sa.String(512), nullable=True),
        sa.Column("preferred_username", sa.String(255), nullable=False),
        sa.Column("display_name", sa.String(255), nullable=True),
        sa.Column("summary", sa.Text, nullable=True),
        sa.Column("icon_url", sa.String(512), nullable=True),
        sa.Column("public_key_pem", sa.Text, nullable=True),
        sa.Column("domain", sa.String(255), nullable=False),
        sa.Column("fetched_at", sa.DateTime(timezone=True), server_default=sa.func.now(), nullable=False),
        sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.func.now(), nullable=False),
    )
    op.create_index("ix_ap_remote_actor_url", "ap_remote_actors", ["actor_url"], unique=True)
    op.create_index("ix_ap_remote_actor_domain", "ap_remote_actors", ["domain"])

    # -- ap_following --
    op.create_table(
        "ap_following",
        sa.Column("id", sa.Integer, primary_key=True, autoincrement=True),
        sa.Column("actor_profile_id", sa.Integer, sa.ForeignKey("ap_actor_profiles.id", ondelete="CASCADE"), nullable=False),
        sa.Column("remote_actor_id", sa.Integer, sa.ForeignKey("ap_remote_actors.id", ondelete="CASCADE"), nullable=False),
        sa.Column("state", sa.String(20), nullable=False, server_default="pending"),
        sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.func.now(), nullable=False),
        sa.Column("accepted_at", sa.DateTime(timezone=True), nullable=True),
        sa.UniqueConstraint("actor_profile_id", "remote_actor_id", name="uq_following"),
    )
    op.create_index("ix_ap_following_actor", "ap_following", ["actor_profile_id"])
    op.create_index("ix_ap_following_remote", "ap_following", ["remote_actor_id"])

    # -- ap_remote_posts --
    op.create_table(
        "ap_remote_posts",
        sa.Column("id", sa.Integer, primary_key=True, autoincrement=True),
        sa.Column("remote_actor_id", sa.Integer, sa.ForeignKey("ap_remote_actors.id", ondelete="CASCADE"), nullable=False),
        sa.Column("activity_id", sa.String(512), unique=True, nullable=False),
        sa.Column("object_id", sa.String(512), unique=True, nullable=False),
        sa.Column("object_type", sa.String(64), nullable=False, server_default="Note"),
        sa.Column("content", sa.Text, nullable=True),
        sa.Column("summary", sa.Text, nullable=True),
        sa.Column("url", sa.String(512), nullable=True),
        sa.Column("attachment_data", JSONB, nullable=True),
        sa.Column("tag_data", JSONB, nullable=True),
        sa.Column("in_reply_to", sa.String(512), nullable=True),
        sa.Column("conversation", sa.String(512), nullable=True),
        sa.Column("published", sa.DateTime(timezone=True), nullable=True),
        sa.Column("fetched_at", sa.DateTime(timezone=True), server_default=sa.func.now(), nullable=False),
        sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.func.now(), nullable=False),
    )
    op.create_index("ix_ap_remote_post_actor", "ap_remote_posts", ["remote_actor_id"])
    op.create_index("ix_ap_remote_post_published", "ap_remote_posts", ["published"])
    op.create_index("ix_ap_remote_post_object", "ap_remote_posts", ["object_id"], unique=True)

    # -- ap_local_posts --
    op.create_table(
        "ap_local_posts",
        sa.Column("id", sa.Integer, primary_key=True, autoincrement=True),
        sa.Column("actor_profile_id", sa.Integer, sa.ForeignKey("ap_actor_profiles.id", ondelete="CASCADE"), nullable=False),
        sa.Column("content", sa.Text, nullable=False),
        sa.Column("visibility", sa.String(20), nullable=False, server_default="public"),
        sa.Column("in_reply_to", sa.String(512), nullable=True),
        sa.Column("published", sa.DateTime(timezone=True), server_default=sa.func.now(), nullable=False),
        sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.func.now(), nullable=False),
        sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.func.now(), nullable=False),
    )
    op.create_index("ix_ap_local_post_actor", "ap_local_posts", ["actor_profile_id"])
    op.create_index("ix_ap_local_post_published", "ap_local_posts", ["published"])

    # -- ap_interactions --
    op.create_table(
        "ap_interactions",
        sa.Column("id", sa.Integer, primary_key=True, autoincrement=True),
        sa.Column("actor_profile_id", sa.Integer, sa.ForeignKey("ap_actor_profiles.id", ondelete="CASCADE"), nullable=True),
        sa.Column("remote_actor_id", sa.Integer, sa.ForeignKey("ap_remote_actors.id", ondelete="CASCADE"), nullable=True),
        sa.Column("post_type", sa.String(20), nullable=False),
        sa.Column("post_id", sa.Integer, nullable=False),
        sa.Column("interaction_type", sa.String(20), nullable=False),
        sa.Column("activity_id", sa.String(512), nullable=True),
        sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.func.now(), nullable=False),
    )
    op.create_index("ix_ap_interaction_post", "ap_interactions", ["post_type", "post_id"])
    op.create_index("ix_ap_interaction_actor", "ap_interactions", ["actor_profile_id"])
    op.create_index("ix_ap_interaction_remote", "ap_interactions", ["remote_actor_id"])

    # -- ap_notifications --
    op.create_table(
        "ap_notifications",
        sa.Column("id", sa.Integer, primary_key=True, autoincrement=True),
        sa.Column("actor_profile_id", sa.Integer, sa.ForeignKey("ap_actor_profiles.id", ondelete="CASCADE"), nullable=False),
        sa.Column("notification_type", sa.String(20), nullable=False),
        sa.Column("from_remote_actor_id", sa.Integer, sa.ForeignKey("ap_remote_actors.id", ondelete="SET NULL"), nullable=True),
        sa.Column("from_actor_profile_id", sa.Integer, sa.ForeignKey("ap_actor_profiles.id", ondelete="SET NULL"), nullable=True),
        sa.Column("target_activity_id", sa.Integer, sa.ForeignKey("ap_activities.id", ondelete="SET NULL"), nullable=True),
        sa.Column("target_remote_post_id", sa.Integer, sa.ForeignKey("ap_remote_posts.id", ondelete="SET NULL"), nullable=True),
        sa.Column("read", sa.Boolean, nullable=False, server_default="false"),
        sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.func.now(), nullable=False),
    )
    op.create_index("ix_ap_notification_actor", "ap_notifications", ["actor_profile_id"])
    op.create_index("ix_ap_notification_read", "ap_notifications", ["actor_profile_id", "read"])
    op.create_index("ix_ap_notification_created", "ap_notifications", ["created_at"])


def downgrade() -> None:
    op.drop_table("ap_notifications")
    op.drop_table("ap_interactions")
    op.drop_table("ap_local_posts")
    op.drop_table("ap_remote_posts")
    op.drop_table("ap_following")
    op.drop_table("ap_remote_actors")
