"""Wire RLS into the saas-membership pack.

v1.0.0 declared app_subscription with a required app_user_id data field but no
rls_enabled -- nothing at Cloud stopped one app user from reading or writing
another user's subscription/entitlement row; any scoping had to be hand-rolled
in the generated app's BFF. Same gap client-portal had, fixed the same way
here: add rls_enabled: true to app_subscription. This is deterministic, not a
guess -- app_subscription already carries its owning app_user_id in its own
data (it was a required field even at v1.0.0), same as client_account was for
client-portal (see 109_client_portal_rls.py).

Existing installs: PackInstallService.install_pack reconciles rls_enabled on
an already-existing entity via patch_project_entity when create returns
already_exists, so re-running codegen (or an explicit pack reinstall) turns
RLS on for a project that installed saas-membership before this migration.
That does not retroactively fix owner_user_id on records created before RLS
existed -- see scripts/backfill_saas_membership_ownership.py, run once per
already-installed project after reinstalling.

Revision ID: 122
Revises: 121
"""
from datetime import datetime, timezone

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

revision = "122"
down_revision = "121"
branch_labels = None
depends_on = None

feature_packs = sa.table(
    "feature_packs",
    sa.column("slug", sa.String),
    sa.column("version", sa.String),
    sa.column("composition", postgresql.JSONB),
    sa.column("updated_at", sa.DateTime(timezone=True)),
)

_APP_SUBSCRIPTION_ENTITY_V1 = {
    "entity_key": "app_subscription",
    "name": "App Subscription",
    "plural_name": "App Subscriptions",
    "schema": {
        "fields": [
            {"key": "app_user_id", "name": "App User", "type": "text", "required": True, "indexed": True},
            # Reconciled from Stripe webhooks — never trust a client-supplied plan/status.
            {"key": "stripe_customer_id", "name": "Stripe Customer ID", "type": "text", "indexed": True},
            {"key": "stripe_subscription_id", "name": "Stripe Subscription ID", "type": "text", "indexed": True},
            {"key": "status", "name": "Status", "type": "select",
             "options": ["trialing", "active", "past_due", "canceled", "unpaid"], "indexed": True},
            {"key": "plan_key", "name": "Plan Key", "type": "text", "indexed": True},
            {"key": "current_period_end", "name": "Current Period End", "type": "date"},
        ],
    },
}

_APP_SUBSCRIPTION_ENTITY_V1_1 = {**_APP_SUBSCRIPTION_ENTITY_V1, "rls_enabled": True}

_COMPOSITION_V1_1 = {
    "function_slugs": [],
    "entities": [_APP_SUBSCRIPTION_ENTITY_V1_1],
    "connector_actions": [
        "stripe.create_customer",
        "stripe.create_checkout",
        "stripe.create_subscription",
        "stripe.retrieve_subscription",
        "stripe.cancel_subscription",
        "stripe.create_billing_portal_session",
    ],
    "requires": ["stripe"],
}

_COMPOSITION_V1_0 = {
    "function_slugs": [],
    "entities": [_APP_SUBSCRIPTION_ENTITY_V1],
    "connector_actions": [
        "stripe.create_customer",
        "stripe.create_checkout",
        "stripe.create_subscription",
        "stripe.retrieve_subscription",
        "stripe.cancel_subscription",
        "stripe.create_billing_portal_session",
    ],
    "requires": ["stripe"],
}


def upgrade() -> None:
    op.execute(
        sa.update(feature_packs)
        .where(feature_packs.c.slug == "saas-membership")
        .values(
            version="1.1.0",
            composition=_COMPOSITION_V1_1,
            updated_at=datetime.now(timezone.utc),
        )
    )


def downgrade() -> None:
    op.execute(
        sa.update(feature_packs)
        .where(feature_packs.c.slug == "saas-membership")
        .values(
            version="1.0.0",
            composition=_COMPOSITION_V1_0,
            updated_at=datetime.now(timezone.utc),
        )
    )
