"""Phase 7.5 — Referral Engine (programs, codes, attributions)."""
from alembic import op
import sqlalchemy as sa

revision = "0006_phase_75_referral"
down_revision = "0005_phase_74_campaigns"
branch_labels = None
depends_on = None


def upgrade():
    op.create_table(
        "referral_programs",
        sa.Column("id", sa.CHAR(length=36), primary_key=True),
        sa.Column("tenant_id", sa.CHAR(length=36), nullable=False),
        sa.Column("program_id", sa.CHAR(length=36), nullable=False),
        sa.Column("code", sa.String(length=50), nullable=False),
        sa.Column("name", sa.String(length=255), nullable=False),
        sa.Column("status", sa.String(length=20), nullable=False),
        sa.Column(
            "referrer_bonus_points", sa.Integer(), nullable=False, server_default="0"
        ),
        sa.Column(
            "referee_bonus_points", sa.Integer(), nullable=False, server_default="0"
        ),
        sa.Column("max_referrals_per_member", sa.Integer(), nullable=True),
        sa.Column(
            "is_deleted", sa.Boolean(), nullable=False, server_default=sa.false()
        ),
        sa.Column("deleted_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("deleted_by", sa.String(length=100), nullable=True),
        sa.Column("created_by", sa.String(length=100), nullable=True),
        sa.Column("updated_by", sa.String(length=100), nullable=True),
        sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
        sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False),
        sa.UniqueConstraint(
            "tenant_id",
            "program_id",
            "code",
            name="uq_referral_programs_tenant_program_code",
        ),
    )
    op.create_index(
        "ix_referral_programs_tenant_status",
        "referral_programs",
        ["tenant_id", "status"],
    )
    op.create_index(
        "ix_referral_programs_tenant_deleted",
        "referral_programs",
        ["tenant_id", "is_deleted"],
    )

    op.create_table(
        "referral_codes",
        sa.Column("id", sa.CHAR(length=36), primary_key=True),
        sa.Column("tenant_id", sa.CHAR(length=36), nullable=False),
        sa.Column("referral_program_id", sa.CHAR(length=36), nullable=False),
        sa.Column("program_id", sa.CHAR(length=36), nullable=False),
        sa.Column("member_id", sa.CHAR(length=36), nullable=False),
        sa.Column("code", sa.String(length=50), nullable=False),
        sa.Column("status", sa.String(length=20), nullable=False),
        sa.Column("uses_count", sa.Integer(), nullable=False, server_default="0"),
        sa.Column("created_by", sa.String(length=100), nullable=True),
        sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
        sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False),
        sa.UniqueConstraint(
            "tenant_id", "code", name="uq_referral_codes_tenant_code"
        ),
    )
    op.create_index(
        "ix_referral_codes_program_member",
        "referral_codes",
        ["tenant_id", "referral_program_id", "member_id"],
    )

    op.create_table(
        "referral_attributions",
        sa.Column("id", sa.CHAR(length=36), primary_key=True),
        sa.Column("tenant_id", sa.CHAR(length=36), nullable=False),
        sa.Column("referral_program_id", sa.CHAR(length=36), nullable=False),
        sa.Column("referral_code_id", sa.CHAR(length=36), nullable=False),
        sa.Column("program_id", sa.CHAR(length=36), nullable=False),
        sa.Column("referrer_member_id", sa.CHAR(length=36), nullable=False),
        sa.Column("referee_member_id", sa.CHAR(length=36), nullable=False),
        sa.Column("status", sa.String(length=20), nullable=False),
        sa.Column("referrer_ledger_entry_id", sa.CHAR(length=36), nullable=True),
        sa.Column("referee_ledger_entry_id", sa.CHAR(length=36), nullable=True),
        sa.Column("idempotency_key", sa.String(length=100), nullable=True),
        sa.Column("converted_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("rewarded_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("cancelled_at", sa.DateTime(timezone=True), nullable=True),
        sa.Column("cancel_reason", sa.String(length=500), nullable=True),
        sa.Column("actor_user_id", sa.String(length=100), nullable=True),
        sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
        sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False),
        sa.UniqueConstraint(
            "tenant_id",
            "referral_program_id",
            "referee_member_id",
            name="uq_referral_attributions_tenant_program_referee",
        ),
        sa.UniqueConstraint(
            "tenant_id",
            "idempotency_key",
            name="uq_referral_attributions_tenant_idempotency",
        ),
    )
    op.create_index(
        "ix_referral_attributions_referrer",
        "referral_attributions",
        ["tenant_id", "referral_program_id", "referrer_member_id"],
    )
    op.create_index(
        "ix_referral_attributions_status",
        "referral_attributions",
        ["tenant_id", "status"],
    )


def downgrade():
    op.drop_index(
        "ix_referral_attributions_status", table_name="referral_attributions"
    )
    op.drop_index(
        "ix_referral_attributions_referrer", table_name="referral_attributions"
    )
    op.drop_table("referral_attributions")

    op.drop_index("ix_referral_codes_program_member", table_name="referral_codes")
    op.drop_table("referral_codes")

    op.drop_index(
        "ix_referral_programs_tenant_deleted", table_name="referral_programs"
    )
    op.drop_index(
        "ix_referral_programs_tenant_status", table_name="referral_programs"
    )
    op.drop_table("referral_programs")
