"""org billing subscriptions invoices

Revision ID: e40df94401d2
Revises: 7a35e59fc400
Create Date: 2025-11-08 00:50:51.480663

"""

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

# revision identifiers, used by Alembic.
revision = "e40df94401d2"
down_revision = "7a35e59fc400"
branch_labels = None
depends_on = None


def upgrade() -> None:
  # ### commands auto generated by Alembic - please adjust! ###
  op.create_table(
    "orgs",
    sa.Column("id", sa.String(), nullable=False),
    sa.Column("name", sa.String(), nullable=False),
    sa.Column(
      "org_type",
      sa.Enum("PERSONAL", "TEAM", "ENTERPRISE", name="orgtype"),
      nullable=False,
    ),
    sa.Column("created_at", sa.DateTime(), nullable=False),
    sa.Column("updated_at", sa.DateTime(), nullable=False),
    sa.Column("deleted_at", sa.DateTime(), nullable=True),
    sa.PrimaryKeyConstraint("id"),
  )
  op.create_table(
    "billing_customers",
    sa.Column("org_id", sa.String(), nullable=False),
    sa.Column("stripe_customer_id", sa.String(), nullable=True),
    sa.Column("has_payment_method", sa.Boolean(), nullable=False),
    sa.Column("default_payment_method_id", sa.String(), nullable=True),
    sa.Column("invoice_billing_enabled", sa.Boolean(), nullable=False),
    sa.Column("billing_email", sa.String(), nullable=True),
    sa.Column("billing_contact_name", sa.String(), nullable=True),
    sa.Column("payment_terms", sa.String(), nullable=False),
    sa.Column("created_at", sa.DateTime(), nullable=False),
    sa.Column("updated_at", sa.DateTime(), nullable=False),
    sa.ForeignKeyConstraint(
      ["org_id"],
      ["orgs.id"],
    ),
    sa.PrimaryKeyConstraint("org_id"),
    sa.UniqueConstraint("stripe_customer_id"),
  )
  op.create_table(
    "billing_invoices",
    sa.Column("id", sa.String(), nullable=False),
    sa.Column("org_id", sa.String(), nullable=False),
    sa.Column("invoice_number", sa.String(), nullable=False),
    sa.Column("period_start", sa.DateTime(), nullable=False),
    sa.Column("period_end", sa.DateTime(), nullable=False),
    sa.Column("subtotal_cents", sa.Integer(), nullable=False),
    sa.Column("tax_cents", sa.Integer(), nullable=False),
    sa.Column("discount_cents", sa.Integer(), nullable=False),
    sa.Column("total_cents", sa.Integer(), nullable=False),
    sa.Column("status", sa.String(), nullable=False),
    sa.Column("stripe_invoice_id", sa.String(), nullable=True),
    sa.Column("sent_at", sa.DateTime(), nullable=True),
    sa.Column("due_date", sa.DateTime(), nullable=True),
    sa.Column("paid_at", sa.DateTime(), nullable=True),
    sa.Column("payment_method", sa.String(), nullable=True),
    sa.Column("payment_reference", sa.String(), nullable=True),
    sa.Column("notes", sa.String(), nullable=True),
    sa.Column("created_at", sa.DateTime(), nullable=False),
    sa.Column("updated_at", sa.DateTime(), nullable=False),
    sa.ForeignKeyConstraint(
      ["org_id"],
      ["orgs.id"],
    ),
    sa.PrimaryKeyConstraint("id"),
    sa.UniqueConstraint("invoice_number"),
    sa.UniqueConstraint("stripe_invoice_id"),
  )
  op.create_index(
    "idx_billing_invoice_due_date", "billing_invoices", ["due_date"], unique=False
  )
  op.create_index(
    "idx_billing_invoice_org", "billing_invoices", ["org_id"], unique=False
  )
  op.create_index(
    "idx_billing_invoice_period",
    "billing_invoices",
    ["period_start", "period_end"],
    unique=False,
  )
  op.create_index(
    "idx_billing_invoice_status", "billing_invoices", ["status"], unique=False
  )
  op.create_table(
    "billing_subscriptions",
    sa.Column("id", sa.String(), nullable=False),
    sa.Column("org_id", sa.String(), nullable=False),
    sa.Column("resource_type", sa.String(), nullable=False),
    sa.Column("resource_id", sa.String(), nullable=True),
    sa.Column("plan_name", sa.String(), nullable=False),
    sa.Column("billing_interval", sa.String(), nullable=False),
    sa.Column("base_price_cents", sa.Integer(), nullable=False),
    sa.Column("stripe_subscription_id", sa.String(), nullable=True),
    sa.Column("stripe_product_id", sa.String(), nullable=True),
    sa.Column("stripe_price_id", sa.String(), nullable=True),
    sa.Column("payment_provider", sa.String(), nullable=False),
    sa.Column("provider_subscription_id", sa.String(), nullable=True),
    sa.Column("provider_customer_id", sa.String(), nullable=True),
    sa.Column(
      "subscription_metadata",
      postgresql.JSONB(astext_type=sa.Text()),
      server_default="{}",
      nullable=False,
    ),
    sa.Column("status", sa.String(), nullable=False),
    sa.Column("started_at", sa.DateTime(), nullable=True),
    sa.Column("current_period_start", sa.DateTime(), nullable=True),
    sa.Column("current_period_end", sa.DateTime(), nullable=True),
    sa.Column("canceled_at", sa.DateTime(), nullable=True),
    sa.Column("ends_at", sa.DateTime(), nullable=True),
    sa.Column("created_at", sa.DateTime(), nullable=False),
    sa.Column("updated_at", sa.DateTime(), nullable=False),
    sa.ForeignKeyConstraint(
      ["org_id"],
      ["orgs.id"],
    ),
    sa.PrimaryKeyConstraint("id"),
    sa.UniqueConstraint("provider_subscription_id"),
    sa.UniqueConstraint("stripe_subscription_id"),
  )
  op.create_index(
    "idx_billing_sub_org", "billing_subscriptions", ["org_id"], unique=False
  )
  op.create_index(
    "idx_billing_sub_provider",
    "billing_subscriptions",
    ["provider_subscription_id"],
    unique=False,
  )
  op.create_index(
    "idx_billing_sub_resource",
    "billing_subscriptions",
    ["resource_type", "resource_id"],
    unique=False,
  )
  op.create_index(
    "idx_billing_sub_status", "billing_subscriptions", ["status"], unique=False
  )
  op.create_index(
    "idx_billing_sub_stripe",
    "billing_subscriptions",
    ["stripe_subscription_id"],
    unique=False,
  )
  op.create_table(
    "org_limits",
    sa.Column("id", sa.String(), nullable=False),
    sa.Column("org_id", sa.String(), nullable=False),
    sa.Column("max_graphs", sa.Integer(), nullable=False),
    sa.Column("created_at", sa.DateTime(), nullable=False),
    sa.Column("updated_at", sa.DateTime(), nullable=False),
    sa.ForeignKeyConstraint(
      ["org_id"],
      ["orgs.id"],
    ),
    sa.PrimaryKeyConstraint("id"),
    sa.UniqueConstraint("org_id"),
  )
  op.create_table(
    "org_users",
    sa.Column("id", sa.String(), nullable=False),
    sa.Column("org_id", sa.String(), nullable=False),
    sa.Column("user_id", sa.String(), nullable=False),
    sa.Column(
      "role", sa.Enum("OWNER", "ADMIN", "MEMBER", name="orgrole"), nullable=False
    ),
    sa.Column("joined_at", sa.DateTime(), nullable=False),
    sa.Column("updated_at", sa.DateTime(), nullable=False),
    sa.ForeignKeyConstraint(
      ["org_id"],
      ["orgs.id"],
    ),
    sa.ForeignKeyConstraint(
      ["user_id"],
      ["users.id"],
    ),
    sa.PrimaryKeyConstraint("id"),
    sa.UniqueConstraint("org_id", "user_id", name="uq_org_user"),
  )
  op.create_index(op.f("ix_org_users_org_id"), "org_users", ["org_id"], unique=False)
  op.create_index(op.f("ix_org_users_user_id"), "org_users", ["user_id"], unique=False)
  op.create_table(
    "billing_audit_logs",
    sa.Column("id", sa.String(), nullable=False),
    sa.Column("event_type", sa.String(), nullable=False),
    sa.Column("event_timestamp", sa.DateTime(), nullable=False),
    sa.Column("org_id", sa.String(), nullable=True),
    sa.Column("subscription_id", sa.String(), nullable=True),
    sa.Column("invoice_id", sa.String(), nullable=True),
    sa.Column("event_data", sa.JSON(), nullable=True),
    sa.Column("description", sa.String(), nullable=False),
    sa.Column("actor_user_id", sa.String(), nullable=True),
    sa.Column("actor_type", sa.String(), nullable=False),
    sa.Column("actor_ip", sa.String(), nullable=True),
    sa.Column("created_at", sa.DateTime(), nullable=False),
    sa.ForeignKeyConstraint(
      ["actor_user_id"],
      ["users.id"],
    ),
    sa.ForeignKeyConstraint(
      ["invoice_id"],
      ["billing_invoices.id"],
    ),
    sa.ForeignKeyConstraint(
      ["org_id"],
      ["orgs.id"],
    ),
    sa.ForeignKeyConstraint(
      ["subscription_id"],
      ["billing_subscriptions.id"],
    ),
    sa.PrimaryKeyConstraint("id"),
  )
  op.create_index(
    "idx_billing_audit_actor", "billing_audit_logs", ["actor_user_id"], unique=False
  )
  op.create_index(
    "idx_billing_audit_event_type", "billing_audit_logs", ["event_type"], unique=False
  )
  op.create_index(
    "idx_billing_audit_invoice", "billing_audit_logs", ["invoice_id"], unique=False
  )
  op.create_index(
    "idx_billing_audit_org", "billing_audit_logs", ["org_id"], unique=False
  )
  op.create_index(
    "idx_billing_audit_subscription",
    "billing_audit_logs",
    ["subscription_id"],
    unique=False,
  )
  op.create_index(
    "idx_billing_audit_timestamp",
    "billing_audit_logs",
    ["event_timestamp"],
    unique=False,
  )
  op.create_table(
    "billing_invoice_line_items",
    sa.Column("id", sa.String(), nullable=False),
    sa.Column("invoice_id", sa.String(), nullable=False),
    sa.Column("subscription_id", sa.String(), nullable=True),
    sa.Column("resource_type", sa.String(), nullable=False),
    sa.Column("resource_id", sa.String(), nullable=False),
    sa.Column("description", sa.String(), nullable=False),
    sa.Column("quantity", sa.Integer(), nullable=False),
    sa.Column("unit_price_cents", sa.Integer(), nullable=False),
    sa.Column("amount_cents", sa.Integer(), nullable=False),
    sa.Column("period_start", sa.DateTime(), nullable=False),
    sa.Column("period_end", sa.DateTime(), nullable=False),
    sa.Column("line_metadata", sa.JSON(), nullable=True),
    sa.Column("created_at", sa.DateTime(), nullable=False),
    sa.ForeignKeyConstraint(
      ["invoice_id"],
      ["billing_invoices.id"],
    ),
    sa.ForeignKeyConstraint(
      ["subscription_id"],
      ["billing_subscriptions.id"],
    ),
    sa.PrimaryKeyConstraint("id"),
  )
  op.create_index(
    "idx_billing_line_item_invoice",
    "billing_invoice_line_items",
    ["invoice_id"],
    unique=False,
  )
  op.create_index(
    "idx_billing_line_item_resource",
    "billing_invoice_line_items",
    ["resource_type", "resource_id"],
    unique=False,
  )
  op.create_index(
    "idx_billing_line_item_subscription",
    "billing_invoice_line_items",
    ["subscription_id"],
    unique=False,
  )
  op.create_table(
    "graph_users",
    sa.Column("id", sa.String(), nullable=False),
    sa.Column("user_id", sa.String(), nullable=False),
    sa.Column("graph_id", sa.String(), nullable=False),
    sa.Column("role", sa.String(), nullable=False),
    sa.Column("is_selected", sa.Boolean(), nullable=False),
    sa.Column("created_at", sa.DateTime(), nullable=False),
    sa.Column("updated_at", sa.DateTime(), nullable=False),
    sa.ForeignKeyConstraint(
      ["graph_id"],
      ["graphs.graph_id"],
    ),
    sa.ForeignKeyConstraint(
      ["user_id"],
      ["users.id"],
    ),
    sa.PrimaryKeyConstraint("id"),
    sa.UniqueConstraint("graph_id", "user_id", name="_graph_user_uc"),
  )
  op.create_index(
    "idx_graph_users_graph_user_id",
    "graph_users",
    ["graph_id", "user_id"],
    unique=False,
  )
  op.create_index(
    "idx_graph_users_user_selected",
    "graph_users",
    ["user_id", "is_selected"],
    unique=False,
  )
  op.create_index(
    op.f("ix_graph_users_graph_id"), "graph_users", ["graph_id"], unique=False
  )
  op.create_index(
    op.f("ix_graph_users_user_id"), "graph_users", ["user_id"], unique=False
  )
  op.drop_table("user_limits")
  op.drop_index(op.f("idx_user_graphs_user_graph_id"), table_name="user_graphs")
  op.drop_index(op.f("idx_user_graphs_user_selected"), table_name="user_graphs")
  op.drop_index(op.f("ix_user_graphs_graph_id"), table_name="user_graphs")
  op.drop_index(op.f("ix_user_graphs_user_id"), table_name="user_graphs")
  op.drop_table("user_graphs")
  op.drop_table("graph_subscriptions")
  op.add_column("graphs", sa.Column("org_id", sa.String(), nullable=True))
  op.create_index("idx_graphs_org", "graphs", ["org_id"], unique=False)
  op.create_foreign_key(None, "graphs", "orgs", ["org_id"], ["id"])
  # ### end Alembic commands ###


def downgrade() -> None:
  # ### commands auto generated by Alembic - please adjust! ###
  op.drop_constraint(None, "graphs", type_="foreignkey")
  op.drop_index("idx_graphs_org", table_name="graphs")
  op.drop_column("graphs", "org_id")
  op.create_table(
    "graph_subscriptions",
    sa.Column("id", sa.VARCHAR(), autoincrement=False, nullable=False),
    sa.Column("user_id", sa.VARCHAR(), autoincrement=False, nullable=False),
    sa.Column("graph_id", sa.VARCHAR(), autoincrement=False, nullable=False),
    sa.Column("plan_name", sa.VARCHAR(), autoincrement=False, nullable=True),
    sa.Column(
      "status",
      postgresql.ENUM(
        "ACTIVE", "PAST_DUE", "CANCELED", "UNPAID", name="subscriptionstatus"
      ),
      autoincrement=False,
      nullable=False,
    ),
    sa.Column(
      "current_period_start",
      postgresql.TIMESTAMP(timezone=True),
      autoincrement=False,
      nullable=True,
    ),
    sa.Column(
      "current_period_end",
      postgresql.TIMESTAMP(timezone=True),
      autoincrement=False,
      nullable=True,
    ),
    sa.Column(
      "created_at",
      postgresql.TIMESTAMP(timezone=True),
      autoincrement=False,
      nullable=False,
    ),
    sa.Column(
      "updated_at",
      postgresql.TIMESTAMP(timezone=True),
      autoincrement=False,
      nullable=False,
    ),
    sa.ForeignKeyConstraint(
      ["user_id"], ["users.id"], name=op.f("graph_subscriptions_user_id_fkey")
    ),
    sa.PrimaryKeyConstraint("id", name=op.f("graph_subscriptions_pkey")),
  )
  op.create_table(
    "user_graphs",
    sa.Column("id", sa.VARCHAR(), autoincrement=False, nullable=False),
    sa.Column("user_id", sa.VARCHAR(), autoincrement=False, nullable=False),
    sa.Column("graph_id", sa.VARCHAR(), autoincrement=False, nullable=False),
    sa.Column("role", sa.VARCHAR(), autoincrement=False, nullable=False),
    sa.Column("is_selected", sa.BOOLEAN(), autoincrement=False, nullable=False),
    sa.Column(
      "created_at", postgresql.TIMESTAMP(), autoincrement=False, nullable=False
    ),
    sa.Column(
      "updated_at", postgresql.TIMESTAMP(), autoincrement=False, nullable=False
    ),
    sa.ForeignKeyConstraint(
      ["graph_id"], ["graphs.graph_id"], name=op.f("user_graphs_graph_id_fkey")
    ),
    sa.ForeignKeyConstraint(
      ["user_id"], ["users.id"], name=op.f("user_graphs_user_id_fkey")
    ),
    sa.PrimaryKeyConstraint("id", name=op.f("user_graphs_pkey")),
    sa.UniqueConstraint(
      "user_id",
      "graph_id",
      name=op.f("_user_graph_uc"),
      postgresql_include=[],
      postgresql_nulls_not_distinct=False,
    ),
  )
  op.create_index(
    op.f("ix_user_graphs_user_id"), "user_graphs", ["user_id"], unique=False
  )
  op.create_index(
    op.f("ix_user_graphs_graph_id"), "user_graphs", ["graph_id"], unique=False
  )
  op.create_index(
    op.f("idx_user_graphs_user_selected"),
    "user_graphs",
    ["user_id", "is_selected"],
    unique=False,
  )
  op.create_index(
    op.f("idx_user_graphs_user_graph_id"),
    "user_graphs",
    ["user_id", "graph_id"],
    unique=False,
  )
  op.create_table(
    "user_limits",
    sa.Column("id", sa.VARCHAR(), autoincrement=False, nullable=False),
    sa.Column("user_id", sa.VARCHAR(), autoincrement=False, nullable=False),
    sa.Column("max_user_graphs", sa.INTEGER(), autoincrement=False, nullable=False),
    sa.Column(
      "created_at", postgresql.TIMESTAMP(), autoincrement=False, nullable=False
    ),
    sa.Column(
      "updated_at", postgresql.TIMESTAMP(), autoincrement=False, nullable=False
    ),
    sa.ForeignKeyConstraint(
      ["user_id"], ["users.id"], name=op.f("user_limits_user_id_fkey")
    ),
    sa.PrimaryKeyConstraint("id", name=op.f("user_limits_pkey")),
    sa.UniqueConstraint(
      "user_id",
      name=op.f("user_limits_user_id_key"),
      postgresql_include=[],
      postgresql_nulls_not_distinct=False,
    ),
  )
  op.drop_index(op.f("ix_graph_users_user_id"), table_name="graph_users")
  op.drop_index(op.f("ix_graph_users_graph_id"), table_name="graph_users")
  op.drop_index("idx_graph_users_user_selected", table_name="graph_users")
  op.drop_index("idx_graph_users_graph_user_id", table_name="graph_users")
  op.drop_table("graph_users")
  op.drop_index(
    "idx_billing_line_item_subscription", table_name="billing_invoice_line_items"
  )
  op.drop_index(
    "idx_billing_line_item_resource", table_name="billing_invoice_line_items"
  )
  op.drop_index(
    "idx_billing_line_item_invoice", table_name="billing_invoice_line_items"
  )
  op.drop_table("billing_invoice_line_items")
  op.drop_index("idx_billing_audit_timestamp", table_name="billing_audit_logs")
  op.drop_index("idx_billing_audit_subscription", table_name="billing_audit_logs")
  op.drop_index("idx_billing_audit_org", table_name="billing_audit_logs")
  op.drop_index("idx_billing_audit_invoice", table_name="billing_audit_logs")
  op.drop_index("idx_billing_audit_event_type", table_name="billing_audit_logs")
  op.drop_index("idx_billing_audit_actor", table_name="billing_audit_logs")
  op.drop_table("billing_audit_logs")
  op.drop_index(op.f("ix_org_users_user_id"), table_name="org_users")
  op.drop_index(op.f("ix_org_users_org_id"), table_name="org_users")
  op.drop_table("org_users")
  op.drop_table("org_limits")
  op.drop_index("idx_billing_sub_stripe", table_name="billing_subscriptions")
  op.drop_index("idx_billing_sub_status", table_name="billing_subscriptions")
  op.drop_index("idx_billing_sub_resource", table_name="billing_subscriptions")
  op.drop_index("idx_billing_sub_provider", table_name="billing_subscriptions")
  op.drop_index("idx_billing_sub_org", table_name="billing_subscriptions")
  op.drop_table("billing_subscriptions")
  op.drop_index("idx_billing_invoice_status", table_name="billing_invoices")
  op.drop_index("idx_billing_invoice_period", table_name="billing_invoices")
  op.drop_index("idx_billing_invoice_org", table_name="billing_invoices")
  op.drop_index("idx_billing_invoice_due_date", table_name="billing_invoices")
  op.drop_table("billing_invoices")
  op.drop_table("billing_customers")
  op.drop_table("orgs")
  # ### end Alembic commands ###
