"""Initial migration

Revision ID: 185e37df3252
Revises:
Create Date: 2025-11-05 15:26:35.759743

"""

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

# revision identifiers, used by Alembic.
revision = "185e37df3252"
down_revision = None
branch_labels = None
depends_on = None


def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table(
        "active_user_record",
        sa.Column(
            "id",
            mysql.BIGINT(),
            autoincrement=True,
            nullable=False,
            comment="Unique ID",
        ),
        sa.Column(
            "record_id", sa.String(length=36), nullable=False, comment="Record UUID"
        ),
        sa.Column(
            "active_id", sa.String(length=36), nullable=False, comment="Active UUID"
        ),
        sa.Column(
            "active_name", sa.String(length=255), nullable=False, comment="Active name"
        ),
        sa.Column("user_id", sa.String(length=36), nullable=False, comment="User UUID"),
        sa.Column(
            "price",
            sa.Numeric(precision=10, scale=2),
            nullable=False,
            comment="Price of the active",
        ),
        sa.Column(
            "order_id", sa.String(length=36), nullable=False, comment="Order UUID"
        ),
        sa.Column(
            "status", sa.Integer(), nullable=False, comment="Status of the record"
        ),
        sa.Column("created", sa.TIMESTAMP(), nullable=False, comment="Creation time"),
        sa.Column("updated", sa.TIMESTAMP(), nullable=False, comment="Update time"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_table(
        "ai_course_auth",
        sa.Column("id", mysql.BIGINT(), autoincrement=True, nullable=False),
        sa.Column(
            "course_auth_id",
            sa.String(length=36),
            nullable=False,
            comment="course_auth_id UUID",
        ),
        sa.Column(
            "course_id", sa.String(length=36), nullable=False, comment="course_id UUID"
        ),
        sa.Column("user_id", sa.String(length=36), nullable=False, comment="User UUID"),
        sa.Column(
            "auth_type", sa.String(length=255), nullable=False, comment="auth_info"
        ),
        sa.Column("status", sa.Integer(), nullable=False, comment="Status"),
        sa.Column(
            "created_at", sa.TIMESTAMP(), nullable=False, comment="Creation time"
        ),
        sa.Column("updated_at", sa.TIMESTAMP(), nullable=False, comment="Update time"),
        sa.PrimaryKeyConstraint("id"),
    )
    with op.batch_alter_table("ai_course_auth", schema=None) as batch_op:
        batch_op.create_index(
            batch_op.f("ix_ai_course_auth_course_auth_id"),
            ["course_auth_id"],
            unique=False,
        )

    op.create_table(
        "learn_generated_blocks",
        sa.Column("id", mysql.BIGINT(), autoincrement=True, nullable=False),
        sa.Column(
            "generated_block_bid",
            sa.String(length=36),
            nullable=False,
            comment="Learn block log business identifier",
        ),
        sa.Column(
            "progress_record_bid",
            sa.String(length=36),
            nullable=False,
            comment="Learn outline item business identifier",
        ),
        sa.Column(
            "user_bid",
            sa.String(length=36),
            nullable=False,
            comment="User business identifier",
        ),
        sa.Column(
            "block_bid",
            sa.String(length=36),
            nullable=False,
            comment="Block business identifier",
        ),
        sa.Column(
            "outline_item_bid",
            sa.String(length=36),
            nullable=False,
            comment="Outline business identifier",
        ),
        sa.Column(
            "shifu_bid",
            sa.String(length=36),
            nullable=False,
            comment="Shifu business identifier",
        ),
        sa.Column("type", sa.Integer(), nullable=False, comment="Block content type"),
        sa.Column("role", sa.Integer(), nullable=False, comment="Block role"),
        sa.Column(
            "generated_content",
            sa.Text(),
            nullable=False,
            comment="Block generate content",
        ),
        sa.Column(
            "position", sa.Integer(), nullable=False, comment="Block position index"
        ),
        sa.Column(
            "block_content_conf",
            sa.Text(),
            nullable=False,
            comment="Block content config(used for re-generate)",
        ),
        sa.Column(
            "liked",
            sa.Integer(),
            nullable=False,
            comment="Interaction type: -1=disliked, 0=not available, 1=liked",
        ),
        sa.Column(
            "deleted",
            sa.SmallInteger(),
            nullable=False,
            comment="Deletion flag: 0=active, 1=deleted",
        ),
        sa.Column(
            "status",
            sa.Integer(),
            nullable=False,
            comment="Status of the record: 1=active, 0=history",
        ),
        sa.Column("created_at", sa.DateTime(), nullable=False, comment="Creation time"),
        sa.Column("updated_at", sa.DateTime(), nullable=False, comment="Update time"),
        sa.PrimaryKeyConstraint("id"),
        comment="Learn generated blocks",
    )
    with op.batch_alter_table("learn_generated_blocks", schema=None) as batch_op:
        batch_op.create_index(
            batch_op.f("ix_learn_generated_blocks_block_bid"),
            ["block_bid"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_learn_generated_blocks_generated_block_bid"),
            ["generated_block_bid"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_learn_generated_blocks_outline_item_bid"),
            ["outline_item_bid"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_learn_generated_blocks_progress_record_bid"),
            ["progress_record_bid"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_learn_generated_blocks_shifu_bid"),
            ["shifu_bid"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_learn_generated_blocks_user_bid"), ["user_bid"], unique=False
        )

    op.create_table(
        "learn_progress_records",
        sa.Column("id", mysql.BIGINT(), autoincrement=True, nullable=False),
        sa.Column(
            "progress_record_bid",
            sa.String(length=36),
            nullable=False,
            comment="Learn outline item business identifier",
        ),
        sa.Column(
            "shifu_bid",
            sa.String(length=36),
            nullable=False,
            comment="Shifu business identifier",
        ),
        sa.Column(
            "outline_item_bid",
            sa.String(length=36),
            nullable=False,
            comment="Outline business identifier",
        ),
        sa.Column(
            "user_bid",
            sa.String(length=36),
            nullable=False,
            comment="User business identifier",
        ),
        sa.Column(
            "outline_item_updated",
            sa.Integer(),
            nullable=False,
            comment="Outline is updated",
        ),
        sa.Column(
            "status",
            sa.SmallInteger(),
            nullable=False,
            comment="Status: 601=not started, 602=in progress, 603=completed, 604=refund, 605=locked, 606=unavailable, 607=branch, 608=reset",
        ),
        sa.Column(
            "block_position",
            sa.Integer(),
            nullable=False,
            comment="Block position index of the outlineitem",
        ),
        sa.Column(
            "deleted",
            sa.SmallInteger(),
            nullable=False,
            comment="Deletion flag: 0=active, 1=deleted",
        ),
        sa.Column("created_at", sa.DateTime(), nullable=False, comment="Creation time"),
        sa.Column("updated_at", sa.DateTime(), nullable=False, comment="Update time"),
        sa.PrimaryKeyConstraint("id"),
        comment="Learn progress records",
    )
    with op.batch_alter_table("learn_progress_records", schema=None) as batch_op:
        batch_op.create_index(
            batch_op.f("ix_learn_progress_records_outline_item_bid"),
            ["outline_item_bid"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_learn_progress_records_progress_record_bid"),
            ["progress_record_bid"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_learn_progress_records_shifu_bid"),
            ["shifu_bid"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_learn_progress_records_status"), ["status"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_learn_progress_records_user_bid"), ["user_bid"], unique=False
        )

    op.create_table(
        "order_banner_info",
        sa.Column("id", mysql.BIGINT(), autoincrement=True, nullable=False),
        sa.Column(
            "banner_id",
            sa.String(length=36),
            nullable=False,
            comment="Banner identifier",
        ),
        sa.Column(
            "course_id",
            sa.String(length=36),
            nullable=False,
            comment="Course identifier",
        ),
        sa.Column("show_banner", sa.Integer(), nullable=False, comment="Show banner"),
        sa.Column(
            "show_lesson_banner",
            sa.Integer(),
            nullable=False,
            comment="Show lesson banner",
        ),
        sa.Column(
            "deleted",
            sa.SmallInteger(),
            nullable=False,
            comment="Deletion flag: 0=active, 1=deleted",
        ),
        sa.Column("created_at", sa.DateTime(), nullable=False, comment="Creation time"),
        sa.Column(
            "created_user_bid",
            sa.String(length=32),
            nullable=False,
            comment="Creator user business identifier",
        ),
        sa.Column("updated_at", sa.DateTime(), nullable=False, comment="Update time"),
        sa.Column(
            "updated_user_bid",
            sa.String(length=32),
            nullable=False,
            comment="Last updater user business identifier",
        ),
        sa.PrimaryKeyConstraint("id"),
        comment="Order banner info",
    )
    with op.batch_alter_table("order_banner_info", schema=None) as batch_op:
        batch_op.create_index(
            batch_op.f("ix_order_banner_info_banner_id"), ["banner_id"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_order_banner_info_course_id"), ["course_id"], unique=False
        )

    op.create_table(
        "order_orders",
        sa.Column("id", mysql.BIGINT(), autoincrement=True, nullable=False),
        sa.Column(
            "order_bid",
            sa.String(length=36),
            nullable=False,
            comment="Order business identifier",
        ),
        sa.Column(
            "shifu_bid",
            sa.String(length=36),
            nullable=False,
            comment="Shifu business identifier",
        ),
        sa.Column(
            "user_bid",
            sa.String(length=36),
            nullable=False,
            comment="User business identifier",
        ),
        sa.Column(
            "payable_price",
            sa.Numeric(precision=10, scale=2),
            nullable=False,
            comment="Shifu original price",
        ),
        sa.Column(
            "paid_price",
            sa.Numeric(precision=10, scale=2),
            nullable=False,
            comment="Paid price",
        ),
        sa.Column(
            "status",
            sa.SmallInteger(),
            nullable=False,
            comment="Status of the order: 501=init, 502=paid, 503=refunded, 504=unpaid, 505=timeout",
        ),
        sa.Column(
            "deleted",
            sa.SmallInteger(),
            nullable=False,
            comment="Deletion flag: 0=active, 1=deleted",
        ),
        sa.Column("created_at", sa.DateTime(), nullable=False, comment="Creation time"),
        sa.Column("updated_at", sa.DateTime(), nullable=False, comment="Update time"),
        sa.PrimaryKeyConstraint("id"),
        comment="Order orders",
    )
    with op.batch_alter_table("order_orders", schema=None) as batch_op:
        batch_op.create_index(
            batch_op.f("ix_order_orders_order_bid"), ["order_bid"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_order_orders_shifu_bid"), ["shifu_bid"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_order_orders_user_bid"), ["user_bid"], unique=False
        )

    op.create_table(
        "order_pingxx_orders",
        sa.Column("id", mysql.BIGINT(), autoincrement=True, nullable=False),
        sa.Column(
            "pingxx_order_bid",
            sa.String(length=36),
            nullable=False,
            comment="Pingxx order business identifier",
        ),
        sa.Column(
            "user_bid",
            sa.String(length=36),
            nullable=False,
            comment="User business identifier",
        ),
        sa.Column(
            "shifu_bid",
            sa.String(length=36),
            nullable=False,
            comment="Shifu business identifier",
        ),
        sa.Column(
            "order_bid",
            sa.String(length=36),
            nullable=False,
            comment="Order business identifier",
        ),
        sa.Column(
            "transaction_no",
            sa.String(length=36),
            nullable=False,
            comment="Pingxx transaction number",
        ),
        sa.Column(
            "app_id",
            sa.String(length=36),
            nullable=False,
            comment="Pingxx app identifier",
        ),
        sa.Column(
            "channel", sa.String(length=36), nullable=False, comment="Payment channel"
        ),
        sa.Column("amount", mysql.BIGINT(), nullable=False, comment="Payment amount"),
        sa.Column("currency", sa.String(length=36), nullable=False, comment="Currency"),
        sa.Column(
            "subject", sa.String(length=255), nullable=False, comment="Payment subject"
        ),
        sa.Column(
            "body", sa.String(length=255), nullable=False, comment="Payment body"
        ),
        sa.Column(
            "client_ip", sa.String(length=255), nullable=False, comment="Client IP"
        ),
        sa.Column("extra", sa.Text(), nullable=False, comment="Extra information"),
        sa.Column(
            "status",
            sa.SmallInteger(),
            nullable=False,
            comment="Status of the order: 0=unpaid, 1=paid, 2=refunded, 3=closed, 4=failed",
        ),
        sa.Column(
            "charge_id",
            sa.String(length=255),
            nullable=False,
            comment="Charge identifier",
        ),
        sa.Column("paid_at", sa.DateTime(), nullable=False, comment="Payment time"),
        sa.Column("refunded_at", sa.DateTime(), nullable=False, comment="Refund time"),
        sa.Column("closed_at", sa.DateTime(), nullable=False, comment="Close time"),
        sa.Column("failed_at", sa.DateTime(), nullable=False, comment="Failed time"),
        sa.Column(
            "refund_id",
            sa.String(length=255),
            nullable=False,
            comment="Refund identifier",
        ),
        sa.Column(
            "failure_code",
            sa.String(length=255),
            nullable=False,
            comment="Failure code",
        ),
        sa.Column(
            "failure_msg",
            sa.String(length=255),
            nullable=False,
            comment="Failure message",
        ),
        sa.Column(
            "charge_object",
            sa.Text(),
            nullable=False,
            comment="Pingxx raw charge object",
        ),
        sa.Column(
            "deleted",
            sa.SmallInteger(),
            nullable=False,
            comment="Deletion flag: 0=active, 1=deleted",
        ),
        sa.Column("created_at", sa.DateTime(), nullable=False, comment="Creation time"),
        sa.Column("updated_at", sa.DateTime(), nullable=False, comment="Update time"),
        sa.PrimaryKeyConstraint("id"),
        comment="Order pingxx orders",
    )
    with op.batch_alter_table("order_pingxx_orders", schema=None) as batch_op:
        batch_op.create_index(
            batch_op.f("ix_order_pingxx_orders_app_id"), ["app_id"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_order_pingxx_orders_charge_id"), ["charge_id"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_order_pingxx_orders_order_bid"), ["order_bid"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_order_pingxx_orders_pingxx_order_bid"),
            ["pingxx_order_bid"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_order_pingxx_orders_refund_id"), ["refund_id"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_order_pingxx_orders_shifu_bid"), ["shifu_bid"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_order_pingxx_orders_transaction_no"),
            ["transaction_no"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_order_pingxx_orders_user_bid"), ["user_bid"], unique=False
        )

    op.create_table(
        "profile_item",
        sa.Column(
            "id",
            mysql.BIGINT(),
            autoincrement=True,
            nullable=False,
            comment="Unique ID",
        ),
        sa.Column(
            "profile_id", sa.String(length=36), nullable=False, comment="Profile ID"
        ),
        sa.Column(
            "parent_id",
            sa.String(length=36),
            nullable=False,
            comment="Parent ID: now is shifu_bid",
        ),
        sa.Column(
            "profile_index", sa.Integer(), nullable=False, comment="Profile index"
        ),
        sa.Column(
            "profile_key", sa.String(length=255), nullable=False, comment="Profile key"
        ),
        sa.Column(
            "profile_type",
            sa.Integer(),
            nullable=False,
            comment="profile type: 2900=input_unconf, 2901=input_text, 2902=input_number, 2903=input_select, 2904=input_sex, 2905=input_date",
        ),
        sa.Column(
            "profile_value_type",
            sa.Integer(),
            nullable=False,
            comment="profile value type: 3001=all, 3002=specific",
        ),
        sa.Column(
            "profile_show_type",
            sa.Integer(),
            nullable=False,
            comment="profile show type: 3001=all, 3002=user, 3003=course, 3004=hidden",
        ),
        sa.Column(
            "profile_remark", sa.Text(), nullable=False, comment="Profile remark"
        ),
        sa.Column(
            "profile_prompt_type",
            sa.Integer(),
            nullable=False,
            comment="profile prompt type: 3101=profile, 3102=item",
        ),
        sa.Column(
            "profile_raw_prompt",
            sa.Text(),
            nullable=False,
            comment="Profile raw prompt",
        ),
        sa.Column(
            "profile_prompt", sa.Text(), nullable=False, comment="Profile prompt"
        ),
        sa.Column(
            "profile_prompt_model",
            sa.Text(),
            nullable=False,
            comment="Profile prompt model",
        ),
        sa.Column(
            "profile_prompt_model_args",
            sa.Text(),
            nullable=False,
            comment="Profile prompt model args",
        ),
        sa.Column(
            "profile_color_setting",
            sa.String(length=255),
            nullable=False,
            comment="Profile color",
        ),
        sa.Column(
            "profile_script_id",
            sa.String(length=36),
            nullable=False,
            comment="Profile script id",
        ),
        sa.Column("created", sa.TIMESTAMP(), nullable=False, comment="Creation time"),
        sa.Column("updated", sa.TIMESTAMP(), nullable=False, comment="Update time"),
        sa.Column(
            "status",
            sa.Integer(),
            nullable=False,
            comment="0 for deleted, 1 for active",
        ),
        sa.Column(
            "created_by", sa.String(length=36), nullable=False, comment="Created by"
        ),
        sa.Column(
            "updated_by", sa.String(length=36), nullable=False, comment="Updated by"
        ),
        sa.PrimaryKeyConstraint("id"),
        sa.UniqueConstraint("profile_id"),
    )
    with op.batch_alter_table("profile_item", schema=None) as batch_op:
        batch_op.create_index(
            batch_op.f("ix_profile_item_parent_id"), ["parent_id"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_profile_item_profile_key"), ["profile_key"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_profile_item_profile_script_id"),
            ["profile_script_id"],
            unique=False,
        )

    op.create_table(
        "profile_item_i18n",
        sa.Column(
            "id",
            mysql.BIGINT(),
            autoincrement=True,
            nullable=False,
            comment="Unique ID",
        ),
        sa.Column(
            "parent_id", sa.String(length=36), nullable=False, comment="parent_id"
        ),
        sa.Column(
            "conf_type",
            sa.Integer(),
            nullable=False,
            comment="profile conf type: 3101=profile, 3102=item",
        ),
        sa.Column(
            "language", sa.String(length=255), nullable=False, comment="Language"
        ),
        sa.Column(
            "profile_item_remark",
            sa.Text(),
            nullable=False,
            comment="Profile item remark",
        ),
        sa.Column("created", sa.TIMESTAMP(), nullable=False, comment="Creation time"),
        sa.Column("updated", sa.TIMESTAMP(), nullable=False, comment="Update time"),
        sa.Column(
            "status",
            sa.Integer(),
            nullable=False,
            comment="0 for deleted, 1 for active",
        ),
        sa.Column(
            "created_by", sa.String(length=36), nullable=False, comment="Created by"
        ),
        sa.Column(
            "updated_by", sa.String(length=36), nullable=False, comment="Updated by"
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    with op.batch_alter_table("profile_item_i18n", schema=None) as batch_op:
        batch_op.create_index(
            batch_op.f("ix_profile_item_i18n_language"), ["language"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_profile_item_i18n_parent_id"), ["parent_id"], unique=False
        )

    op.create_table(
        "profile_item_value",
        sa.Column(
            "id",
            mysql.BIGINT(),
            autoincrement=True,
            nullable=False,
            comment="Unique ID",
        ),
        sa.Column(
            "profile_id", sa.String(length=36), nullable=False, comment="Profile ID"
        ),
        sa.Column(
            "profile_item_id",
            sa.String(length=36),
            nullable=False,
            comment="Profile item ID",
        ),
        sa.Column("profile_value", sa.Text(), nullable=False, comment="Profile value"),
        sa.Column(
            "profile_value_index",
            sa.Integer(),
            nullable=False,
            comment="Profile value index",
        ),
        sa.Column("created", sa.TIMESTAMP(), nullable=False, comment="Creation time"),
        sa.Column("updated", sa.TIMESTAMP(), nullable=False, comment="Update time"),
        sa.Column(
            "status",
            sa.Integer(),
            nullable=False,
            comment="0 for deleted, 1 for active",
        ),
        sa.Column(
            "created_by", sa.String(length=36), nullable=False, comment="Created by"
        ),
        sa.Column(
            "updated_by", sa.String(length=36), nullable=False, comment="Updated by"
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    with op.batch_alter_table("profile_item_value", schema=None) as batch_op:
        batch_op.create_index(
            batch_op.f("ix_profile_item_value_profile_id"), ["profile_id"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_profile_item_value_profile_item_id"),
            ["profile_item_id"],
            unique=False,
        )

    op.create_table(
        "promo_coupon_usages",
        sa.Column("id", mysql.BIGINT(), autoincrement=True, nullable=False),
        sa.Column(
            "coupon_usage_bid",
            sa.String(length=36),
            nullable=False,
            comment="Coupon usage business identifier",
        ),
        sa.Column(
            "coupon_bid",
            sa.String(length=36),
            nullable=False,
            comment="Coupon business identifier",
        ),
        sa.Column("name", sa.String(length=255), nullable=False, comment="Coupon name"),
        sa.Column(
            "user_bid",
            sa.String(length=36),
            nullable=False,
            comment="User business identifier",
        ),
        sa.Column(
            "shifu_bid",
            sa.String(length=36),
            nullable=False,
            comment="Shifu business identifier",
        ),
        sa.Column(
            "order_bid",
            sa.String(length=36),
            nullable=False,
            comment="Order business identifier",
        ),
        sa.Column("code", sa.String(length=36), nullable=False, comment="Coupon code"),
        sa.Column(
            "discount_type",
            sa.SmallInteger(),
            nullable=False,
            comment="Coupon Type: 701=fixed, 702=percent",
        ),
        sa.Column(
            "value",
            sa.Numeric(precision=10, scale=2),
            nullable=False,
            comment="Coupon value: would be calculated to amount by coupon type",
        ),
        sa.Column(
            "status",
            sa.SmallInteger(),
            nullable=False,
            comment="Status of the record: 901=inactive, 902=active, 903=used, 904=timeout",
        ),
        sa.Column(
            "deleted",
            sa.SmallInteger(),
            nullable=False,
            comment="Deletion flag: 0=active, 1=deleted",
        ),
        sa.Column(
            "created_at",
            sa.DateTime(),
            server_default=sa.text("now()"),
            nullable=False,
            comment="Creation timestamp",
        ),
        sa.Column(
            "updated_at",
            sa.DateTime(),
            server_default=sa.text("now()"),
            nullable=False,
            comment="Update timestamp",
        ),
        sa.PrimaryKeyConstraint("id"),
        comment="Promo coupon usages",
    )
    with op.batch_alter_table("promo_coupon_usages", schema=None) as batch_op:
        batch_op.create_index(
            batch_op.f("ix_promo_coupon_usages_coupon_bid"),
            ["coupon_bid"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_promo_coupon_usages_coupon_usage_bid"),
            ["coupon_usage_bid"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_promo_coupon_usages_order_bid"), ["order_bid"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_promo_coupon_usages_shifu_bid"), ["shifu_bid"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_promo_coupon_usages_user_bid"), ["user_bid"], unique=False
        )

    op.create_table(
        "promo_coupons",
        sa.Column("id", mysql.BIGINT(), autoincrement=True, nullable=False),
        sa.Column(
            "coupon_bid",
            sa.String(length=36),
            nullable=False,
            comment="Coupon business identifier",
        ),
        sa.Column("code", sa.String(length=36), nullable=False, comment="Coupon code"),
        sa.Column(
            "discount_type",
            sa.SmallInteger(),
            nullable=False,
            comment="Coupon type: 701=fixed, 702=percent",
        ),
        sa.Column(
            "usage_type",
            sa.SmallInteger(),
            nullable=False,
            comment="Coupon apply type: 801=one coupon code for multiple times, 802=one coupon code for one time",
        ),
        sa.Column(
            "value",
            sa.Numeric(precision=10, scale=2),
            nullable=False,
            comment="Coupon value: would be calculated to amount by coupon type",
        ),
        sa.Column("start", sa.DateTime(), nullable=False, comment="Coupon start time"),
        sa.Column("end", sa.DateTime(), nullable=False, comment="Coupon end time"),
        sa.Column(
            "channel", sa.String(length=36), nullable=False, comment="Coupon channel"
        ),
        sa.Column(
            "filter",
            sa.Text(),
            nullable=False,
            comment="Coupon filter: would be used to filter user and shifu",
        ),
        sa.Column(
            "total_count", mysql.BIGINT(), nullable=False, comment="Coupon total count"
        ),
        sa.Column(
            "used_count", mysql.BIGINT(), nullable=False, comment="Coupon used count"
        ),
        sa.Column(
            "status",
            sa.SmallInteger(),
            nullable=False,
            comment="Status of the discount: 0=inactive, 1=active",
        ),
        sa.Column(
            "deleted",
            sa.SmallInteger(),
            nullable=False,
            comment="Deletion flag: 0=active, 1=deleted",
        ),
        sa.Column(
            "created_at",
            sa.DateTime(),
            server_default=sa.text("now()"),
            nullable=False,
            comment="Creation timestamp",
        ),
        sa.Column(
            "created_user_bid",
            sa.String(length=36),
            nullable=False,
            comment="Creator user business identifier",
        ),
        sa.Column(
            "updated_at",
            sa.DateTime(),
            server_default=sa.text("now()"),
            nullable=False,
            comment="Update timestamp",
        ),
        sa.PrimaryKeyConstraint("id"),
        comment="Promo coupons",
    )
    with op.batch_alter_table("promo_coupons", schema=None) as batch_op:
        batch_op.create_index(
            batch_op.f("ix_promo_coupons_code"), ["code"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_promo_coupons_coupon_bid"), ["coupon_bid"], unique=False
        )

    op.create_table(
        "resource",
        sa.Column("id", mysql.BIGINT(), autoincrement=True, nullable=False),
        sa.Column(
            "resource_id", sa.String(length=36), nullable=False, comment="Resource UUID"
        ),
        sa.Column(
            "name", sa.String(length=255), nullable=False, comment="Resource name"
        ),
        sa.Column("type", sa.Integer(), nullable=False, comment="Resource type"),
        sa.Column(
            "oss_bucket", sa.String(length=255), nullable=False, comment="OSS bucket"
        ),
        sa.Column(
            "oss_name", sa.String(length=255), nullable=False, comment="OSS name"
        ),
        sa.Column("url", sa.String(length=255), nullable=False, comment="Resource URL"),
        sa.Column("status", sa.Integer(), nullable=False, comment="Resource status"),
        sa.Column("is_deleted", sa.Integer(), nullable=False, comment="Is deleted"),
        sa.Column(
            "created_by", sa.String(length=36), nullable=False, comment="Created by"
        ),
        sa.Column(
            "updated_by", sa.String(length=36), nullable=False, comment="Updated by"
        ),
        sa.Column(
            "created_at", sa.TIMESTAMP(), nullable=False, comment="Creation time"
        ),
        sa.Column("updated_at", sa.TIMESTAMP(), nullable=False, comment="Update time"),
        sa.PrimaryKeyConstraint("id"),
    )
    with op.batch_alter_table("resource", schema=None) as batch_op:
        batch_op.create_index(
            batch_op.f("ix_resource_resource_id"), ["resource_id"], unique=False
        )
        batch_op.create_index(batch_op.f("ix_resource_type"), ["type"], unique=False)
        batch_op.create_index(
            batch_op.f("ix_resource_oss_bucket"), ["oss_bucket"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_resource_oss_name"), ["oss_name"], unique=False
        )
        batch_op.create_index(batch_op.f("ix_resource_url"), ["url"], unique=False)
        batch_op.create_index(
            batch_op.f("ix_resource_status"), ["status"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_resource_is_deleted"), ["is_deleted"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_resource_created_by"), ["created_by"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_resource_updated_by"), ["updated_by"], unique=False
        )

    op.create_table(
        "resource_usage",
        sa.Column("id", mysql.BIGINT(), autoincrement=True, nullable=False),
        sa.Column(
            "usage_id", sa.String(length=36), nullable=False, comment="Usage UUID"
        ),
        sa.Column(
            "resource_id", sa.String(length=36), nullable=False, comment="Resource UUID"
        ),
        sa.Column("usage_type", sa.Integer(), nullable=False, comment="Usage type"),
        sa.Column("usage_value", sa.Integer(), nullable=False, comment="Usage value"),
        sa.Column("is_deleted", sa.Integer(), nullable=False, comment="Is deleted"),
        sa.Column(
            "created_by", sa.String(length=36), nullable=False, comment="Created by"
        ),
        sa.Column(
            "updated_by", sa.String(length=36), nullable=False, comment="Updated by"
        ),
        sa.Column(
            "created_at", sa.TIMESTAMP(), nullable=False, comment="Creation time"
        ),
        sa.Column("updated_at", sa.TIMESTAMP(), nullable=False, comment="Update time"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_table(
        "risk_control_result",
        sa.Column(
            "id",
            mysql.BIGINT(),
            autoincrement=True,
            nullable=False,
            comment="Unique ID",
        ),
        sa.Column("chat_id", sa.String(length=36), nullable=False, comment="Chat UUID"),
        sa.Column("user_id", sa.String(length=36), nullable=False, comment="User UUID"),
        sa.Column("text", sa.Text(), nullable=False, comment="Text"),
        sa.Column(
            "check_vendor",
            sa.String(length=255),
            nullable=False,
            comment="Check vendor",
        ),
        sa.Column("check_result", sa.Integer(), nullable=False, comment="Check result"),
        sa.Column("check_resp", sa.Text(), nullable=False, comment="Check response"),
        sa.Column("is_pass", sa.Integer(), nullable=False, comment="Is pass"),
        sa.Column(
            "check_strategy",
            sa.String(length=30),
            nullable=False,
            comment="Check strategy",
        ),
        sa.Column("created", sa.TIMESTAMP(), nullable=False, comment="Creation time"),
        sa.Column("updated", sa.TIMESTAMP(), nullable=False, comment="Update time"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_table(
        "scenario_favorite",
        sa.Column("id", mysql.BIGINT(), autoincrement=True, nullable=False),
        sa.Column(
            "scenario_id", sa.String(length=36), nullable=False, comment="Scenario UUID"
        ),
        sa.Column("user_id", sa.String(length=36), nullable=False, comment="User UUID"),
        sa.Column("status", sa.Integer(), nullable=False, comment="Status"),
        sa.Column(
            "created_at", sa.TIMESTAMP(), nullable=False, comment="Creation time"
        ),
        sa.Column("updated_at", sa.TIMESTAMP(), nullable=False, comment="Update time"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_table(
        "scenario_resource",
        sa.Column("id", mysql.BIGINT(), autoincrement=True, nullable=False),
        sa.Column(
            "resource_resource_id",
            sa.String(length=36),
            nullable=False,
            comment="Resource UUID",
        ),
        sa.Column(
            "scenario_id", sa.String(length=36), nullable=False, comment="Scenario UUID"
        ),
        sa.Column(
            "chapter_id", sa.String(length=36), nullable=False, comment="Chapter UUID"
        ),
        sa.Column(
            "resource_type", sa.Integer(), nullable=False, comment="Resource type"
        ),
        sa.Column(
            "resource_id", sa.String(length=36), nullable=False, comment="Resource UUID"
        ),
        sa.Column("is_deleted", sa.Integer(), nullable=False, comment="Is deleted"),
        sa.Column(
            "created_at", sa.TIMESTAMP(), nullable=False, comment="Creation time"
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    with op.batch_alter_table("scenario_resource", schema=None) as batch_op:
        batch_op.create_index(
            batch_op.f("ix_scenario_resource_chapter_id"), ["chapter_id"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_scenario_resource_resource_id"),
            ["resource_id"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_scenario_resource_resource_resource_id"),
            ["resource_resource_id"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_scenario_resource_scenario_id"),
            ["scenario_id"],
            unique=False,
        )

    op.create_table(
        "shifu_draft_outline_items",
        sa.Column("id", mysql.BIGINT(), autoincrement=True, nullable=False),
        sa.Column(
            "outline_item_bid",
            sa.String(length=32),
            nullable=False,
            comment="Outline item business identifier",
        ),
        sa.Column(
            "shifu_bid",
            sa.String(length=32),
            nullable=False,
            comment="Shifu business identifier",
        ),
        sa.Column(
            "title", sa.String(length=100), nullable=False, comment="Outline item title"
        ),
        sa.Column(
            "type",
            sa.SmallInteger(),
            nullable=False,
            comment="Outline item type: 401=trial, 402=normal",
        ),
        sa.Column(
            "hidden",
            sa.SmallInteger(),
            nullable=False,
            comment="Hidden flag: 0=visible, 1=hidden",
        ),
        sa.Column(
            "parent_bid",
            sa.String(length=32),
            nullable=False,
            comment="Parent outline item business identifier",
        ),
        sa.Column(
            "position",
            sa.String(length=10),
            nullable=False,
            comment="Position in outline",
        ),
        sa.Column(
            "prerequisite_item_bids",
            sa.String(length=500),
            nullable=False,
            comment="Prerequisite outline item business identifiers",
        ),
        sa.Column(
            "llm", sa.String(length=100), nullable=False, comment="LLM model name"
        ),
        sa.Column(
            "llm_temperature",
            sa.DECIMAL(precision=10, scale=2),
            nullable=False,
            comment="LLM temperature parameter",
        ),
        sa.Column(
            "llm_system_prompt", sa.Text(), nullable=False, comment="LLM system prompt"
        ),
        sa.Column(
            "ask_enabled_status",
            sa.SmallInteger(),
            nullable=False,
            comment="Ask agent status: 5101=default, 5102=disabled, 5103=enabled",
        ),
        sa.Column(
            "ask_llm",
            sa.String(length=100),
            nullable=False,
            comment="Ask agent LLM model",
        ),
        sa.Column(
            "ask_llm_temperature",
            sa.DECIMAL(precision=10, scale=2),
            nullable=False,
            comment="Ask mode LLM temperature",
        ),
        sa.Column(
            "ask_llm_system_prompt",
            sa.Text(),
            nullable=False,
            comment="Ask mode LLM system prompt",
        ),
        sa.Column("content", sa.Text(), nullable=False, comment="MarkdownFlow content"),
        sa.Column(
            "deleted",
            sa.SmallInteger(),
            nullable=False,
            comment="Deletion flag: 0=active, 1=deleted",
        ),
        sa.Column(
            "created_at", sa.DateTime(), nullable=False, comment="Creation timestamp"
        ),
        sa.Column(
            "created_user_bid",
            sa.String(length=32),
            nullable=False,
            comment="Creator user business identifier",
        ),
        sa.Column(
            "updated_at", sa.DateTime(), nullable=False, comment="Last update timestamp"
        ),
        sa.Column(
            "updated_user_bid",
            sa.String(length=32),
            nullable=False,
            comment="Last updater user business identifier",
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    with op.batch_alter_table("shifu_draft_outline_items", schema=None) as batch_op:
        batch_op.create_index(
            batch_op.f("ix_shifu_draft_outline_items_outline_item_bid"),
            ["outline_item_bid"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_shifu_draft_outline_items_parent_bid"),
            ["parent_bid"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_shifu_draft_outline_items_position"),
            ["position"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_shifu_draft_outline_items_shifu_bid"),
            ["shifu_bid"],
            unique=False,
        )

    op.create_table(
        "shifu_draft_shifus",
        sa.Column("id", mysql.BIGINT(), autoincrement=True, nullable=False),
        sa.Column(
            "shifu_bid",
            sa.String(length=32),
            nullable=False,
            comment="Shifu business identifier",
        ),
        sa.Column(
            "title", sa.String(length=100), nullable=False, comment="Shifu title"
        ),
        sa.Column(
            "keywords",
            sa.String(length=100),
            nullable=False,
            comment="Associated keywords",
        ),
        sa.Column(
            "description",
            sa.String(length=500),
            nullable=False,
            comment="Shifu description",
        ),
        sa.Column(
            "avatar_res_bid",
            sa.String(length=32),
            nullable=False,
            comment="Avatar resource business identifier",
        ),
        sa.Column(
            "llm", sa.String(length=100), nullable=False, comment="LLM model name"
        ),
        sa.Column(
            "llm_temperature",
            sa.DECIMAL(precision=10, scale=2),
            nullable=False,
            comment="LLM temperature parameter",
        ),
        sa.Column(
            "llm_system_prompt", sa.Text(), nullable=False, comment="LLM system prompt"
        ),
        sa.Column(
            "ask_enabled_status",
            sa.SmallInteger(),
            nullable=False,
            comment="Ask agent status: 5101=default, 5102=disabled, 5103=enabled",
        ),
        sa.Column(
            "ask_llm",
            sa.String(length=100),
            nullable=False,
            comment="Ask agent LLM model",
        ),
        sa.Column(
            "ask_llm_temperature",
            sa.DECIMAL(precision=10, scale=2),
            nullable=False,
            comment="Ask agent LLM temperature",
        ),
        sa.Column(
            "ask_llm_system_prompt",
            sa.Text(),
            nullable=False,
            comment="Ask agent LLM system prompt",
        ),
        sa.Column(
            "price",
            sa.DECIMAL(precision=10, scale=2),
            nullable=False,
            comment="Shifu price",
        ),
        sa.Column(
            "deleted",
            sa.SmallInteger(),
            nullable=False,
            comment="Deletion flag: 0=active, 1=deleted",
        ),
        sa.Column(
            "created_at", sa.DateTime(), nullable=False, comment="Creation timestamp"
        ),
        sa.Column(
            "created_user_bid",
            sa.String(length=32),
            nullable=False,
            comment="Creator user business identifier",
        ),
        sa.Column(
            "updated_at", sa.DateTime(), nullable=False, comment="Last update timestamp"
        ),
        sa.Column(
            "updated_user_bid",
            sa.String(length=32),
            nullable=False,
            comment="Last updater user business identifier",
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    with op.batch_alter_table("shifu_draft_shifus", schema=None) as batch_op:
        batch_op.create_index(
            batch_op.f("ix_shifu_draft_shifus_created_user_bid"),
            ["created_user_bid"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_shifu_draft_shifus_shifu_bid"), ["shifu_bid"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_shifu_draft_shifus_updated_user_bid"),
            ["updated_user_bid"],
            unique=False,
        )

    op.create_table(
        "shifu_log_draft_structs",
        sa.Column("id", mysql.BIGINT(), autoincrement=True, nullable=False),
        sa.Column(
            "struct_bid",
            sa.String(length=32),
            nullable=False,
            comment="Content business identifier",
        ),
        sa.Column(
            "shifu_bid",
            sa.String(length=32),
            nullable=False,
            comment="Shifu business identifier",
        ),
        sa.Column(
            "struct",
            mysql.LONGTEXT(),
            nullable=False,
            comment="JSON serialized shifu struct",
        ),
        sa.Column(
            "deleted",
            sa.SmallInteger(),
            nullable=False,
            comment="Deletion flag: 0=active, 1=deleted",
        ),
        sa.Column(
            "created_at", sa.DateTime(), nullable=False, comment="Creation timestamp"
        ),
        sa.Column(
            "created_user_bid",
            sa.String(length=32),
            nullable=False,
            comment="Creator user business identifier",
        ),
        sa.Column(
            "updated_at", sa.DateTime(), nullable=False, comment="Last update timestamp"
        ),
        sa.Column(
            "updated_user_bid",
            sa.String(length=32),
            nullable=False,
            comment="Last updater user business identifier",
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    with op.batch_alter_table("shifu_log_draft_structs", schema=None) as batch_op:
        batch_op.create_index(
            batch_op.f("ix_shifu_log_draft_structs_shifu_bid"),
            ["shifu_bid"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_shifu_log_draft_structs_struct_bid"),
            ["struct_bid"],
            unique=True,
        )

    op.create_table(
        "shifu_log_published_structs",
        sa.Column("id", mysql.BIGINT(), autoincrement=True, nullable=False),
        sa.Column(
            "struct_bid",
            sa.String(length=32),
            nullable=False,
            comment="Content business identifier",
        ),
        sa.Column(
            "shifu_bid",
            sa.String(length=32),
            nullable=False,
            comment="Shifu business identifier",
        ),
        sa.Column(
            "struct",
            mysql.LONGTEXT(),
            nullable=False,
            comment="JSON serialized struct of published shifu",
        ),
        sa.Column(
            "deleted",
            sa.SmallInteger(),
            nullable=False,
            comment="Deletion flag: 0=active, 1=deleted",
        ),
        sa.Column(
            "created_at", sa.DateTime(), nullable=False, comment="Creation timestamp"
        ),
        sa.Column(
            "created_user_bid",
            sa.String(length=32),
            nullable=False,
            comment="Creator user business identifier",
        ),
        sa.Column(
            "updated_at", sa.DateTime(), nullable=False, comment="Last update timestamp"
        ),
        sa.Column(
            "updated_user_bid",
            sa.String(length=32),
            nullable=False,
            comment="Last updater user business identifier",
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    with op.batch_alter_table("shifu_log_published_structs", schema=None) as batch_op:
        batch_op.create_index(
            batch_op.f("ix_shifu_log_published_structs_shifu_bid"),
            ["shifu_bid"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_shifu_log_published_structs_struct_bid"),
            ["struct_bid"],
            unique=True,
        )

    op.create_table(
        "shifu_published_outline_items",
        sa.Column("id", mysql.BIGINT(), autoincrement=True, nullable=False),
        sa.Column(
            "outline_item_bid",
            sa.String(length=32),
            nullable=False,
            comment="Outline item business identifier",
        ),
        sa.Column(
            "shifu_bid",
            sa.String(length=32),
            nullable=False,
            comment="Shifu business identifier",
        ),
        sa.Column(
            "title", sa.String(length=100), nullable=False, comment="Outline item title"
        ),
        sa.Column(
            "type",
            sa.SmallInteger(),
            nullable=False,
            comment="Outline item type: 401=trial, 402=normal",
        ),
        sa.Column(
            "hidden",
            sa.SmallInteger(),
            nullable=False,
            comment="Hidden flag: 0=visible, 1=hidden",
        ),
        sa.Column(
            "parent_bid",
            sa.String(length=32),
            nullable=False,
            comment="Parent outline item business identifier",
        ),
        sa.Column(
            "position", sa.String(length=10), nullable=False, comment="Outline position"
        ),
        sa.Column(
            "prerequisite_item_bids",
            sa.String(length=500),
            nullable=False,
            comment="Prerequisite outline item business identifiers",
        ),
        sa.Column(
            "llm", sa.String(length=100), nullable=False, comment="LLM model name"
        ),
        sa.Column(
            "llm_temperature",
            sa.DECIMAL(precision=10, scale=2),
            nullable=False,
            comment="LLM temperature parameter",
        ),
        sa.Column(
            "llm_system_prompt", sa.Text(), nullable=False, comment="LLM system prompt"
        ),
        sa.Column(
            "ask_enabled_status",
            sa.SmallInteger(),
            nullable=False,
            comment="Ask agent status: 5101=default, 5102=disabled, 5103=enabled",
        ),
        sa.Column(
            "ask_llm",
            sa.String(length=100),
            nullable=False,
            comment="Ask agent LLM model",
        ),
        sa.Column(
            "ask_llm_temperature",
            sa.DECIMAL(precision=10, scale=2),
            nullable=False,
            comment="Ask agent LLM temperature",
        ),
        sa.Column(
            "ask_llm_system_prompt",
            sa.Text(),
            nullable=False,
            comment="Ask agent LLM system prompt",
        ),
        sa.Column("content", sa.Text(), nullable=False, comment="MarkdownFlow content"),
        sa.Column(
            "deleted",
            sa.SmallInteger(),
            nullable=False,
            comment="Deletion flag: 0=active, 1=deleted",
        ),
        sa.Column(
            "created_at", sa.DateTime(), nullable=False, comment="Creation timestamp"
        ),
        sa.Column(
            "created_user_bid",
            sa.String(length=32),
            nullable=False,
            comment="Creator user business identifier",
        ),
        sa.Column(
            "updated_at", sa.DateTime(), nullable=False, comment="Last update timestamp"
        ),
        sa.Column(
            "updated_user_bid",
            sa.String(length=32),
            nullable=False,
            comment="Last updater user business identifier",
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    with op.batch_alter_table("shifu_published_outline_items", schema=None) as batch_op:
        batch_op.create_index(
            batch_op.f("ix_shifu_published_outline_items_created_user_bid"),
            ["created_user_bid"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_shifu_published_outline_items_outline_item_bid"),
            ["outline_item_bid"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_shifu_published_outline_items_shifu_bid"),
            ["shifu_bid"],
            unique=False,
        )

    op.create_table(
        "shifu_published_shifus",
        sa.Column("id", mysql.BIGINT(), autoincrement=True, nullable=False),
        sa.Column(
            "shifu_bid",
            sa.String(length=32),
            nullable=False,
            comment="Shifu business identifier",
        ),
        sa.Column(
            "title", sa.String(length=100), nullable=False, comment="Shifu title"
        ),
        sa.Column(
            "keywords",
            sa.String(length=100),
            nullable=False,
            comment="Associated keywords",
        ),
        sa.Column(
            "description",
            sa.String(length=500),
            nullable=False,
            comment="Shifu description",
        ),
        sa.Column(
            "avatar_res_bid",
            sa.String(length=32),
            nullable=False,
            comment="Avatar resource business identifier",
        ),
        sa.Column(
            "llm", sa.String(length=100), nullable=False, comment="LLM model name"
        ),
        sa.Column(
            "llm_temperature",
            sa.DECIMAL(precision=10, scale=2),
            nullable=False,
            comment="LLM temperature parameter",
        ),
        sa.Column(
            "llm_system_prompt", sa.Text(), nullable=False, comment="LLM system prompt"
        ),
        sa.Column(
            "ask_enabled_status",
            sa.SmallInteger(),
            nullable=False,
            comment="Ask agent status: 5101=default, 5102=disabled, 5103=enabled",
        ),
        sa.Column(
            "ask_llm",
            sa.String(length=100),
            nullable=False,
            comment="Ask agent LLM model",
        ),
        sa.Column(
            "ask_llm_temperature",
            sa.DECIMAL(precision=10, scale=2),
            nullable=False,
            comment="Ask agent LLM temperature",
        ),
        sa.Column(
            "ask_llm_system_prompt",
            sa.Text(),
            nullable=False,
            comment="Ask agent LLM system prompt",
        ),
        sa.Column(
            "price",
            sa.DECIMAL(precision=10, scale=2),
            nullable=False,
            comment="Shifu price",
        ),
        sa.Column(
            "deleted",
            sa.SmallInteger(),
            nullable=False,
            comment="Deletion flag: 0=active, 1=deleted",
        ),
        sa.Column(
            "created_at", sa.DateTime(), nullable=False, comment="Creation timestamp"
        ),
        sa.Column(
            "created_user_bid",
            sa.String(length=32),
            nullable=False,
            comment="Creator user business identifier",
        ),
        sa.Column(
            "updated_at", sa.DateTime(), nullable=False, comment="Last update timestamp"
        ),
        sa.Column(
            "updated_user_bid",
            sa.String(length=32),
            nullable=False,
            comment="Last updater user business identifier",
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    with op.batch_alter_table("shifu_published_shifus", schema=None) as batch_op:
        batch_op.create_index(
            batch_op.f("ix_shifu_published_shifus_created_user_bid"),
            ["created_user_bid"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_shifu_published_shifus_shifu_bid"),
            ["shifu_bid"],
            unique=False,
        )

    op.create_table(
        "user_auth_credentials",
        sa.Column(
            "id",
            mysql.BIGINT(),
            autoincrement=True,
            nullable=False,
            comment="Unique ID",
        ),
        sa.Column(
            "credential_bid",
            sa.String(length=32),
            nullable=False,
            comment="Credential business identifier",
        ),
        sa.Column(
            "user_bid",
            sa.String(length=32),
            nullable=False,
            comment="User business identifier",
        ),
        sa.Column(
            "provider_name",
            sa.String(length=255),
            nullable=False,
            comment="Provider name",
        ),
        sa.Column(
            "subject_id", sa.String(length=255), nullable=False, comment="Subject id"
        ),
        sa.Column(
            "subject_format",
            sa.String(length=255),
            nullable=False,
            comment="Subject format",
        ),
        sa.Column(
            "identifier", sa.String(length=255), nullable=False, comment="Identifier"
        ),
        sa.Column("raw_profile", sa.Text(), nullable=False, comment="Raw profile"),
        sa.Column(
            "state",
            sa.Integer(),
            nullable=False,
            comment="Credential state: 1201=unverified, 1202=verified",
        ),
        sa.Column(
            "deleted",
            sa.SmallInteger(),
            nullable=False,
            comment="Deletion flag: 0=active, 1=deleted",
        ),
        sa.Column(
            "created_at", sa.DateTime(), nullable=False, comment="Creation timestamp"
        ),
        sa.Column(
            "updated_at", sa.DateTime(), nullable=False, comment="Last update timestamp"
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    with op.batch_alter_table("user_auth_credentials", schema=None) as batch_op:
        batch_op.create_index(
            batch_op.f("ix_user_auth_credentials_credential_bid"),
            ["credential_bid"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_user_auth_credentials_deleted"), ["deleted"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_user_auth_credentials_identifier"),
            ["identifier"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_user_auth_credentials_provider_name"),
            ["provider_name"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_user_auth_credentials_state"), ["state"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_user_auth_credentials_subject_format"),
            ["subject_format"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_user_auth_credentials_subject_id"),
            ["subject_id"],
            unique=False,
        )
        batch_op.create_index(
            batch_op.f("ix_user_auth_credentials_user_bid"), ["user_bid"], unique=False
        )

    op.create_table(
        "user_conversion",
        sa.Column(
            "id",
            mysql.BIGINT(),
            autoincrement=True,
            nullable=False,
            comment="Unique ID",
        ),
        sa.Column("user_id", sa.String(length=36), nullable=False, comment="User UUID"),
        sa.Column(
            "conversion_id",
            sa.String(length=36),
            nullable=False,
            comment="Conversion UUID",
        ),
        sa.Column(
            "conversion_source",
            sa.String(length=36),
            nullable=False,
            comment="Conversion type",
        ),
        sa.Column(
            "conversion_status",
            sa.Integer(),
            nullable=False,
            comment="Conversion state",
        ),
        sa.Column(
            "conversion_uuid",
            sa.String(length=36),
            nullable=False,
            comment="Conversion UUID",
        ),
        sa.Column(
            "conversion_third_platform",
            sa.String(length=255),
            nullable=False,
            comment="Conversion third platform",
        ),
        sa.Column("created", sa.TIMESTAMP(), nullable=False, comment="Creation time"),
        sa.Column("updated", sa.TIMESTAMP(), nullable=False, comment="Update time"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_table(
        "user_feedback",
        sa.Column(
            "id",
            mysql.BIGINT(),
            autoincrement=True,
            nullable=False,
            comment="Unique ID",
        ),
        sa.Column("user_id", sa.String(length=36), nullable=False, comment="User UUID"),
        sa.Column(
            "feedback", sa.String(length=300), nullable=False, comment="Feedback"
        ),
        sa.Column("created", sa.TIMESTAMP(), nullable=False, comment="Creation time"),
        sa.Column("updated", sa.TIMESTAMP(), nullable=False, comment="Update time"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_table(
        "user_profile",
        sa.Column(
            "id",
            mysql.BIGINT(),
            autoincrement=True,
            nullable=False,
            comment="Unique ID",
        ),
        sa.Column("user_id", sa.String(length=36), nullable=False, comment="User UUID"),
        sa.Column(
            "profile_id", sa.String(length=36), nullable=False, comment="Profile ID"
        ),
        sa.Column(
            "profile_key", sa.String(length=255), nullable=False, comment="Profile key"
        ),
        sa.Column("profile_value", sa.Text(), nullable=False, comment="Profile value"),
        sa.Column(
            "profile_type",
            sa.Integer(),
            nullable=False,
            comment="profile type: 2900=input_unconf, 2901=input_text, 2902=input_number, 2903=input_select, 2904=input_sex, 2905=input_date",
        ),
        sa.Column("created", sa.TIMESTAMP(), nullable=False, comment="Creation time"),
        sa.Column("updated", sa.TIMESTAMP(), nullable=False, comment="Update time"),
        sa.Column(
            "status",
            sa.Integer(),
            nullable=False,
            comment="0 for deleted, 1 for active",
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    with op.batch_alter_table("user_profile", schema=None) as batch_op:
        batch_op.create_index(
            batch_op.f("ix_user_profile_profile_id"), ["profile_id"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_user_profile_profile_key"), ["profile_key"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_user_profile_user_id"), ["user_id"], unique=False
        )

    op.create_table(
        "user_token",
        sa.Column(
            "id",
            mysql.BIGINT(),
            autoincrement=True,
            nullable=False,
            comment="Unique ID",
        ),
        sa.Column("user_id", sa.String(length=36), nullable=False, comment="User UUID"),
        sa.Column("token", sa.String(length=255), nullable=False, comment="Token"),
        sa.Column("token_type", sa.Integer(), nullable=False, comment="Token type"),
        sa.Column(
            "token_expired_at",
            sa.TIMESTAMP(),
            nullable=True,
            comment="Token expired time",
        ),
        sa.Column("created", sa.TIMESTAMP(), nullable=False, comment="Creation time"),
        sa.Column("updated", sa.TIMESTAMP(), nullable=False, comment="Update time"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_table(
        "user_users",
        sa.Column(
            "id",
            mysql.BIGINT(),
            autoincrement=True,
            nullable=False,
            comment="Unique ID",
        ),
        sa.Column(
            "user_bid",
            sa.String(length=32),
            nullable=False,
            comment="User business identifier",
        ),
        sa.Column(
            "user_identify",
            sa.String(length=255),
            nullable=False,
            comment="User identifier: phone or email",
        ),
        sa.Column(
            "nickname", sa.String(length=255), nullable=False, comment="User nickname"
        ),
        sa.Column(
            "avatar", sa.String(length=255), nullable=False, comment="User avatar"
        ),
        sa.Column("birthday", sa.Date(), nullable=True, comment="User birthday"),
        sa.Column(
            "language", sa.String(length=30), nullable=False, comment="User language"
        ),
        sa.Column(
            "state",
            sa.Integer(),
            nullable=False,
            comment="User state: 1101=unregistered, 1102=registered, 1103=trail, 1104=paid",
        ),
        sa.Column(
            "is_creator",
            sa.SmallInteger(),
            nullable=False,
            comment="Creator flag: 0=regular user, 1=creator",
        ),
        sa.Column(
            "deleted",
            sa.SmallInteger(),
            nullable=False,
            comment="Deletion flag: 0=active, 1=deleted",
        ),
        sa.Column(
            "created_at", sa.DateTime(), nullable=False, comment="Creation timestamp"
        ),
        sa.Column(
            "updated_at", sa.DateTime(), nullable=False, comment="Last update timestamp"
        ),
        sa.PrimaryKeyConstraint("id"),
    )
    with op.batch_alter_table("user_users", schema=None) as batch_op:
        batch_op.create_index(
            batch_op.f("ix_user_users_deleted"), ["deleted"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_user_users_is_creator"), ["is_creator"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_user_users_state"), ["state"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_user_users_user_bid"), ["user_bid"], unique=False
        )
        batch_op.create_index(
            batch_op.f("ix_user_users_user_identify"), ["user_identify"], unique=False
        )

    op.create_table(
        "user_verify_code",
        sa.Column(
            "id",
            mysql.BIGINT(),
            autoincrement=True,
            nullable=False,
            comment="Unique ID",
        ),
        sa.Column("phone", sa.String(length=36), nullable=False, comment="User phone"),
        sa.Column("mail", sa.String(length=36), nullable=False, comment="User mail"),
        sa.Column(
            "verify_code", sa.String(length=10), nullable=False, comment="Verify code"
        ),
        sa.Column(
            "verify_code_type", sa.Integer(), nullable=False, comment="Verify code type"
        ),
        sa.Column(
            "verify_code_send",
            sa.Integer(),
            nullable=False,
            comment="verification code send state",
        ),
        sa.Column(
            "verify_code_used",
            sa.Integer(),
            nullable=False,
            comment="verification code used state",
        ),
        sa.Column("user_ip", sa.String(length=100), nullable=False, comment="user ip"),
        sa.Column("created", sa.TIMESTAMP(), nullable=False, comment="Creation time"),
        sa.Column("updated", sa.TIMESTAMP(), nullable=False, comment="Update time"),
        sa.PrimaryKeyConstraint("id"),
    )
    # ### end Alembic commands ###


def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_table("user_verify_code")
    with op.batch_alter_table("user_users", schema=None) as batch_op:
        batch_op.drop_index(batch_op.f("ix_user_users_user_identify"))
        batch_op.drop_index(batch_op.f("ix_user_users_user_bid"))
        batch_op.drop_index(batch_op.f("ix_user_users_state"))
        batch_op.drop_index(batch_op.f("ix_user_users_is_creator"))
        batch_op.drop_index(batch_op.f("ix_user_users_deleted"))

    op.drop_table("user_users")
    op.drop_table("user_token")
    with op.batch_alter_table("user_profile", schema=None) as batch_op:
        batch_op.drop_index(batch_op.f("ix_user_profile_user_id"))
        batch_op.drop_index(batch_op.f("ix_user_profile_profile_key"))
        batch_op.drop_index(batch_op.f("ix_user_profile_profile_id"))

    op.drop_table("user_profile")
    op.drop_table("user_feedback")
    op.drop_table("user_conversion")
    with op.batch_alter_table("user_auth_credentials", schema=None) as batch_op:
        batch_op.drop_index(batch_op.f("ix_user_auth_credentials_user_bid"))
        batch_op.drop_index(batch_op.f("ix_user_auth_credentials_subject_id"))
        batch_op.drop_index(batch_op.f("ix_user_auth_credentials_subject_format"))
        batch_op.drop_index(batch_op.f("ix_user_auth_credentials_state"))
        batch_op.drop_index(batch_op.f("ix_user_auth_credentials_provider_name"))
        batch_op.drop_index(batch_op.f("ix_user_auth_credentials_identifier"))
        batch_op.drop_index(batch_op.f("ix_user_auth_credentials_deleted"))
        batch_op.drop_index(batch_op.f("ix_user_auth_credentials_credential_bid"))

    op.drop_table("user_auth_credentials")
    with op.batch_alter_table("shifu_published_shifus", schema=None) as batch_op:
        batch_op.drop_index(batch_op.f("ix_shifu_published_shifus_shifu_bid"))
        batch_op.drop_index(batch_op.f("ix_shifu_published_shifus_created_user_bid"))

    op.drop_table("shifu_published_shifus")
    with op.batch_alter_table("shifu_published_outline_items", schema=None) as batch_op:
        batch_op.drop_index(batch_op.f("ix_shifu_published_outline_items_shifu_bid"))
        batch_op.drop_index(
            batch_op.f("ix_shifu_published_outline_items_outline_item_bid")
        )
        batch_op.drop_index(
            batch_op.f("ix_shifu_published_outline_items_created_user_bid")
        )

    op.drop_table("shifu_published_outline_items")
    with op.batch_alter_table("shifu_log_published_structs", schema=None) as batch_op:
        batch_op.drop_index(batch_op.f("ix_shifu_log_published_structs_struct_bid"))
        batch_op.drop_index(batch_op.f("ix_shifu_log_published_structs_shifu_bid"))

    op.drop_table("shifu_log_published_structs")
    with op.batch_alter_table("shifu_log_draft_structs", schema=None) as batch_op:
        batch_op.drop_index(batch_op.f("ix_shifu_log_draft_structs_struct_bid"))
        batch_op.drop_index(batch_op.f("ix_shifu_log_draft_structs_shifu_bid"))

    op.drop_table("shifu_log_draft_structs")
    with op.batch_alter_table("shifu_draft_shifus", schema=None) as batch_op:
        batch_op.drop_index(batch_op.f("ix_shifu_draft_shifus_updated_user_bid"))
        batch_op.drop_index(batch_op.f("ix_shifu_draft_shifus_shifu_bid"))
        batch_op.drop_index(batch_op.f("ix_shifu_draft_shifus_created_user_bid"))

    op.drop_table("shifu_draft_shifus")
    with op.batch_alter_table("shifu_draft_outline_items", schema=None) as batch_op:
        batch_op.drop_index(batch_op.f("ix_shifu_draft_outline_items_shifu_bid"))
        batch_op.drop_index(batch_op.f("ix_shifu_draft_outline_items_position"))
        batch_op.drop_index(batch_op.f("ix_shifu_draft_outline_items_parent_bid"))
        batch_op.drop_index(batch_op.f("ix_shifu_draft_outline_items_outline_item_bid"))

    op.drop_table("shifu_draft_outline_items")
    with op.batch_alter_table("scenario_resource", schema=None) as batch_op:
        batch_op.drop_index(batch_op.f("ix_scenario_resource_scenario_id"))
        batch_op.drop_index(batch_op.f("ix_scenario_resource_resource_resource_id"))
        batch_op.drop_index(batch_op.f("ix_scenario_resource_resource_id"))
        batch_op.drop_index(batch_op.f("ix_scenario_resource_chapter_id"))

    op.drop_table("scenario_resource")
    op.drop_table("scenario_favorite")
    op.drop_table("risk_control_result")
    op.drop_table("resource_usage")
    op.drop_table("resource")
    with op.batch_alter_table("promo_coupons", schema=None) as batch_op:
        batch_op.drop_index(batch_op.f("ix_promo_coupons_coupon_bid"))
        batch_op.drop_index(batch_op.f("ix_promo_coupons_code"))

    op.drop_table("promo_coupons")
    with op.batch_alter_table("promo_coupon_usages", schema=None) as batch_op:
        batch_op.drop_index(batch_op.f("ix_promo_coupon_usages_user_bid"))
        batch_op.drop_index(batch_op.f("ix_promo_coupon_usages_shifu_bid"))
        batch_op.drop_index(batch_op.f("ix_promo_coupon_usages_order_bid"))
        batch_op.drop_index(batch_op.f("ix_promo_coupon_usages_coupon_usage_bid"))
        batch_op.drop_index(batch_op.f("ix_promo_coupon_usages_coupon_bid"))

    op.drop_table("promo_coupon_usages")
    with op.batch_alter_table("profile_item_value", schema=None) as batch_op:
        batch_op.drop_index(batch_op.f("ix_profile_item_value_profile_item_id"))
        batch_op.drop_index(batch_op.f("ix_profile_item_value_profile_id"))

    op.drop_table("profile_item_value")
    with op.batch_alter_table("profile_item_i18n", schema=None) as batch_op:
        batch_op.drop_index(batch_op.f("ix_profile_item_i18n_parent_id"))
        batch_op.drop_index(batch_op.f("ix_profile_item_i18n_language"))

    op.drop_table("profile_item_i18n")
    with op.batch_alter_table("profile_item", schema=None) as batch_op:
        batch_op.drop_index(batch_op.f("ix_profile_item_profile_script_id"))
        batch_op.drop_index(batch_op.f("ix_profile_item_profile_key"))
        batch_op.drop_index(batch_op.f("ix_profile_item_parent_id"))

    op.drop_table("profile_item")
    with op.batch_alter_table("order_pingxx_orders", schema=None) as batch_op:
        batch_op.drop_index(batch_op.f("ix_order_pingxx_orders_user_bid"))
        batch_op.drop_index(batch_op.f("ix_order_pingxx_orders_transaction_no"))
        batch_op.drop_index(batch_op.f("ix_order_pingxx_orders_shifu_bid"))
        batch_op.drop_index(batch_op.f("ix_order_pingxx_orders_refund_id"))
        batch_op.drop_index(batch_op.f("ix_order_pingxx_orders_pingxx_order_bid"))
        batch_op.drop_index(batch_op.f("ix_order_pingxx_orders_order_bid"))
        batch_op.drop_index(batch_op.f("ix_order_pingxx_orders_charge_id"))
        batch_op.drop_index(batch_op.f("ix_order_pingxx_orders_app_id"))

    op.drop_table("order_pingxx_orders")
    with op.batch_alter_table("order_orders", schema=None) as batch_op:
        batch_op.drop_index(batch_op.f("ix_order_orders_user_bid"))
        batch_op.drop_index(batch_op.f("ix_order_orders_shifu_bid"))
        batch_op.drop_index(batch_op.f("ix_order_orders_order_bid"))

    op.drop_table("order_orders")
    with op.batch_alter_table("order_banner_info", schema=None) as batch_op:
        batch_op.drop_index(batch_op.f("ix_order_banner_info_course_id"))
        batch_op.drop_index(batch_op.f("ix_order_banner_info_banner_id"))

    op.drop_table("order_banner_info")
    with op.batch_alter_table("learn_progress_records", schema=None) as batch_op:
        batch_op.drop_index(batch_op.f("ix_learn_progress_records_user_bid"))
        batch_op.drop_index(batch_op.f("ix_learn_progress_records_status"))
        batch_op.drop_index(batch_op.f("ix_learn_progress_records_shifu_bid"))
        batch_op.drop_index(batch_op.f("ix_learn_progress_records_progress_record_bid"))
        batch_op.drop_index(batch_op.f("ix_learn_progress_records_outline_item_bid"))

    op.drop_table("learn_progress_records")
    with op.batch_alter_table("learn_generated_blocks", schema=None) as batch_op:
        batch_op.drop_index(batch_op.f("ix_learn_generated_blocks_user_bid"))
        batch_op.drop_index(batch_op.f("ix_learn_generated_blocks_shifu_bid"))
        batch_op.drop_index(batch_op.f("ix_learn_generated_blocks_progress_record_bid"))
        batch_op.drop_index(batch_op.f("ix_learn_generated_blocks_outline_item_bid"))
        batch_op.drop_index(batch_op.f("ix_learn_generated_blocks_generated_block_bid"))
        batch_op.drop_index(batch_op.f("ix_learn_generated_blocks_block_bid"))

    op.drop_table("learn_generated_blocks")
    with op.batch_alter_table("ai_course_auth", schema=None) as batch_op:
        batch_op.drop_index(batch_op.f("ix_ai_course_auth_course_auth_id"))

    op.drop_table("ai_course_auth")
    op.drop_table("active_user_record")
    with op.batch_alter_table("active", schema=None) as batch_op:
        batch_op.drop_index(batch_op.f("ix_active_active_status"))
        batch_op.drop_index(batch_op.f("ix_active_active_start_time"))
        batch_op.drop_index(batch_op.f("ix_active_active_end_time"))

    op.drop_table("active")
    # ### end Alembic commands ###
