"""Seed activity-timeline: a governed read-model projection over canonical
domain events, never a second event system and never a Codegen write target.
Phase 11B3.

Revision ID: 138
Revises: 137
"""
from datetime import datetime, timezone
from uuid import uuid4

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

revision = "138"
down_revision = "137"
branch_labels = None
depends_on = None

feature_packs = sa.table(
    "feature_packs",
    sa.column("id", postgresql.UUID(as_uuid=True)),
    sa.column("slug", sa.String),
    sa.column("name", sa.String),
    sa.column("description", sa.Text),
    sa.column("version", sa.String),
    sa.column("tags", postgresql.JSONB),
    sa.column("status", sa.String),
    sa.column("composition", postgresql.JSONB),
    sa.column("input_schema", postgresql.JSONB),
    sa.column("access_policy", postgresql.JSONB),
)

# Field shape mirrors PlatformEventEnvelope (P2HSCloud packages/shared/src/
# integration-events.ts) field-for-field: type->canonical_event_id,
# resource.{type,id}->subject_entity_key/subject_record_id, actor.{type,id)->
# actor_type/actor_id, timestamp->occurred_at, data->payload (bounded). No
# status field, no schema.workflow -- this is an append-only projection, not a
# lifecycle entity. schema_mode is "protected": Codegen must not author writes
# to it (see docs/audits/ACTIVITY_TIMELINE_11B3.md for why -- the entity is
# populated from canonical event consumption, not from generated app code).
#
# NOTE: composition is stamped via stamp_composition() at insert time below --
# install_pack() reads feature_packs.composition directly with no runtime
# stamping call site, so an unstamped blob here would silently ship without
# schema_mode/field_policy ever reaching Cloud. See
# docs/audits/NOTIFICATIONS_IN_APP_11C1.md's correction section.
_ACTIVITY_ENTRY_ENTITY = {
    "entity_key": "activity_entry",
    "name": "Activity Entry",
    "plural_name": "Activity",
    "schema": {
        "fields": [
            {"key": "event_id", "name": "Event ID", "type": "text", "required": True},
            {
                "key": "canonical_event_id", "name": "Event Type", "type": "text",
                "required": True, "indexed": True,
            },
            {
                "key": "subject_entity_key", "name": "Subject Entity", "type": "text",
                "required": True, "indexed": True,
            },
            {
                "key": "subject_record_id", "name": "Subject Record", "type": "text",
                "required": True, "indexed": True,
            },
            {"key": "actor_type", "name": "Actor Type", "type": "text"},
            {"key": "actor_id", "name": "Actor", "type": "text", "indexed": True},
            {"key": "occurred_at", "name": "Occurred At", "type": "text", "indexed": True},
            {
                "key": "category", "name": "Category", "type": "select",
                "required": True, "indexed": True,
                "options": ["created", "status_changed", "completed", "other"],
            },
            {"key": "producer_capability", "name": "Source Capability", "type": "text"},
            {"key": "payload", "name": "Payload", "type": "json"},
        ],
    },
}


def upgrade() -> None:
    from src.domain.feature_packs.normalize import stamp_composition

    now = datetime.now(timezone.utc)
    raw_composition = {
        "function_slugs": [],
        "entities": [_ACTIVITY_ENTRY_ENTITY],
        "connector_actions": [],
        "requires": [],
    }
    op.bulk_insert(
        feature_packs,
        [
            {
                "id": uuid4(),
                "slug": "activity-timeline",
                "name": "Activity Timeline",
                "description": (
                    "Governed read-model projection over canonical domain events "
                    "(10D-10D4) for a subject, referenced by opaque "
                    "(subject_entity_key, subject_record_id). Not a second event "
                    "system: it emits nothing, and this pack's contract grants no "
                    "actor a create/update action -- rows exist only via canonical "
                    "event consumption, never a generated-app write path."
                ),
                "version": "1.0.0",
                "tags": ["workflow", "activity", "operations"],
                "status": "active",
                "composition": stamp_composition("activity-timeline", raw_composition),
                "input_schema": {"type": "object", "properties": {}},
                "access_policy": {"minimum_plan": "free"},
                "created_at": now,
                "updated_at": now,
            },
        ],
    )


def downgrade() -> None:
    op.execute("DELETE FROM feature_packs WHERE slug = 'activity-timeline'")
