"""add entitlement plans and topic sessions

Revision ID: 0014_entitlements_topics
Revises: 0013_question_insight_indexes
"""

from alembic import context, op
import sqlalchemy as sa


revision = "0014_entitlements_topics"
down_revision = "0013_question_insight_indexes"
branch_labels = None
depends_on = None

PRIMARY_KEY_TYPE = sa.BigInteger().with_variant(sa.Integer(), "sqlite")


def upgrade() -> None:
    inspector = None if context.is_offline_mode() else sa.inspect(op.get_bind())
    tables = set() if inspector is None else set(inspector.get_table_names())
    if "sys_entitlement_plan" not in tables:
        op.create_table(
            "sys_entitlement_plan",
            sa.Column("id", PRIMARY_KEY_TYPE, primary_key=True, autoincrement=True),
            sa.Column("name", sa.String(80), nullable=False),
            sa.Column("plan_type", sa.String(30), nullable=False),
            sa.Column("description", sa.String(255), nullable=True),
            sa.Column("validity_days", sa.Integer(), nullable=True),
            sa.Column("monthly_topic_limit", sa.Integer(), nullable=True),
            sa.Column("enable_growth_profile", sa.Integer(), nullable=False, server_default="0"),
            sa.Column("enable_periodic_reports", sa.Integer(), nullable=False, server_default="0"),
            sa.Column("allow_help_card", sa.Integer(), nullable=False, server_default="1"),
            sa.Column("allow_share_draft", sa.Integer(), nullable=False, server_default="1"),
            sa.Column("deduct_quota", sa.Integer(), nullable=False, server_default="1"),
            sa.Column("status", sa.Integer(), nullable=False, server_default="1"),
            sa.Column("sort_order", sa.Integer(), nullable=False, server_default="0"),
            sa.Column("created_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
            sa.Column("updated_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
        )
        op.create_index("ix_sys_entitlement_plan_plan_type", "sys_entitlement_plan", ["plan_type"])
        op.create_index("ix_sys_entitlement_plan_status", "sys_entitlement_plan", ["status"])
        _seed_default_plans()

    if "sys_user_entitlement" not in tables:
        op.create_table(
            "sys_user_entitlement",
            sa.Column("id", PRIMARY_KEY_TYPE, primary_key=True, autoincrement=True),
            sa.Column("user_id", sa.BigInteger(), sa.ForeignKey("sys_user.id"), nullable=False),
            sa.Column("plan_id", sa.BigInteger(), sa.ForeignKey("sys_entitlement_plan.id"), nullable=False),
            sa.Column("status", sa.String(20), nullable=False, server_default="active"),
            sa.Column("effective_at", sa.DateTime(), nullable=True),
            sa.Column("expired_at", sa.DateTime(), nullable=True),
            sa.Column("assigned_by", sa.BigInteger(), nullable=True),
            sa.Column("remark", sa.String(255), nullable=True),
            sa.Column("created_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
            sa.Column("updated_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
        )
        op.create_index("ix_sys_user_entitlement_user_id", "sys_user_entitlement", ["user_id"])
        op.create_index("ix_sys_user_entitlement_plan_id", "sys_user_entitlement", ["plan_id"])
        op.create_index("ix_sys_user_entitlement_status", "sys_user_entitlement", ["status"])

    if "sys_user_entitlement_log" not in tables:
        op.create_table(
            "sys_user_entitlement_log",
            sa.Column("id", PRIMARY_KEY_TYPE, primary_key=True, autoincrement=True),
            sa.Column("user_id", sa.BigInteger(), nullable=False),
            sa.Column("entitlement_id", sa.BigInteger(), nullable=True),
            sa.Column("from_plan_id", sa.BigInteger(), nullable=True),
            sa.Column("to_plan_id", sa.BigInteger(), nullable=True),
            sa.Column("action", sa.String(30), nullable=False),
            sa.Column("detail_json", sa.Text(), nullable=True),
            sa.Column("operated_by", sa.BigInteger(), nullable=True),
            sa.Column("created_at", sa.DateTime(), nullable=False),
        )
        op.create_index("ix_sys_user_entitlement_log_user_id", "sys_user_entitlement_log", ["user_id"])

    if "sys_topic_session" not in tables:
        op.create_table(
            "sys_topic_session",
            sa.Column("id", PRIMARY_KEY_TYPE, primary_key=True, autoincrement=True),
            sa.Column("user_id", sa.BigInteger(), sa.ForeignKey("sys_user.id"), nullable=False),
            sa.Column("chat_session_id", sa.BigInteger(), sa.ForeignKey("sys_chat_session.id"), nullable=False),
            sa.Column("title", sa.String(120), nullable=False),
            sa.Column("core_question", sa.Text(), nullable=False),
            sa.Column("status", sa.String(20), nullable=False, server_default="active"),
            sa.Column("message_count", sa.Integer(), nullable=False, server_default="0"),
            sa.Column("token_input", sa.Integer(), nullable=False, server_default="0"),
            sa.Column("token_output", sa.Integer(), nullable=False, server_default="0"),
            sa.Column("quota_deducted", sa.Integer(), nullable=False, server_default="0"),
            sa.Column("recommended_homework", sa.Text(), nullable=True),
            sa.Column("help_card_generated", sa.Integer(), nullable=False, server_default="0"),
            sa.Column("share_draft_generated", sa.Integer(), nullable=False, server_default="0"),
            sa.Column("started_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
            sa.Column("ended_at", sa.DateTime(), nullable=True),
            sa.Column("created_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
            sa.Column("updated_at", sa.DateTime(), server_default=sa.func.now(), nullable=False),
        )
        op.create_index("ix_sys_topic_session_user_id", "sys_topic_session", ["user_id"])
        op.create_index("ix_sys_topic_session_chat_session_id", "sys_topic_session", ["chat_session_id"])
        op.create_index("ix_sys_topic_session_status", "sys_topic_session", ["status"])

    columns = set() if inspector is None else {column["name"] for column in inspector.get_columns("sys_chat_message")}
    if "topic_session_id" not in columns:
        op.add_column("sys_chat_message", sa.Column("topic_session_id", sa.BigInteger(), nullable=True))
        op.create_index("ix_sys_chat_message_topic_session_id", "sys_chat_message", ["topic_session_id"])


def downgrade() -> None:
    inspector = None if context.is_offline_mode() else sa.inspect(op.get_bind())
    columns = {"topic_session_id"} if inspector is None else {
        column["name"] for column in inspector.get_columns("sys_chat_message")
    }
    if "topic_session_id" in columns:
        op.drop_index("ix_sys_chat_message_topic_session_id", table_name="sys_chat_message")
        op.drop_column("sys_chat_message", "topic_session_id")
    tables = {
        "sys_topic_session",
        "sys_user_entitlement_log",
        "sys_user_entitlement",
        "sys_entitlement_plan",
    } if inspector is None else set(inspector.get_table_names())
    if "sys_topic_session" in tables:
        op.drop_index("ix_sys_topic_session_status", table_name="sys_topic_session")
        op.drop_index("ix_sys_topic_session_chat_session_id", table_name="sys_topic_session")
        op.drop_index("ix_sys_topic_session_user_id", table_name="sys_topic_session")
        op.drop_table("sys_topic_session")
    if "sys_user_entitlement_log" in tables:
        op.drop_index("ix_sys_user_entitlement_log_user_id", table_name="sys_user_entitlement_log")
        op.drop_table("sys_user_entitlement_log")
    if "sys_user_entitlement" in tables:
        op.drop_index("ix_sys_user_entitlement_status", table_name="sys_user_entitlement")
        op.drop_index("ix_sys_user_entitlement_plan_id", table_name="sys_user_entitlement")
        op.drop_index("ix_sys_user_entitlement_user_id", table_name="sys_user_entitlement")
        op.drop_table("sys_user_entitlement")
    if "sys_entitlement_plan" in tables:
        op.drop_index("ix_sys_entitlement_plan_status", table_name="sys_entitlement_plan")
        op.drop_index("ix_sys_entitlement_plan_plan_type", table_name="sys_entitlement_plan")
        op.drop_table("sys_entitlement_plan")


def _seed_default_plans() -> None:
    op.bulk_insert(
        sa.table(
            "sys_entitlement_plan",
            sa.column("name", sa.String(80)),
            sa.column("plan_type", sa.String(30)),
            sa.column("description", sa.String(255)),
            sa.column("validity_days", sa.Integer()),
            sa.column("monthly_topic_limit", sa.Integer()),
            sa.column("enable_growth_profile", sa.Integer()),
            sa.column("enable_periodic_reports", sa.Integer()),
            sa.column("allow_help_card", sa.Integer()),
            sa.column("allow_share_draft", sa.Integer()),
            sa.column("deduct_quota", sa.Integer()),
            sa.column("status", sa.Integer()),
            sa.column("sort_order", sa.Integer()),
        ),
        [
            {
                "name": "大本营基础版",
                "plan_type": "basic",
                "description": "随大本营提供，支持基础知识查询、功课方向和求助卡生成。",
                "validity_days": None,
                "monthly_topic_limit": 30,
                "enable_growth_profile": 0,
                "enable_periodic_reports": 0,
                "allow_help_card": 1,
                "allow_share_draft": 1,
                "deduct_quota": 1,
                "status": 1,
                "sort_order": 10,
            },
            {
                "name": "五个月深度陪伴版",
                "plan_type": "deep",
                "description": "支持近期实修回顾、周期实修回顾和更高主题会话额度。",
                "validity_days": 150,
                "monthly_topic_limit": 90,
                "enable_growth_profile": 1,
                "enable_periodic_reports": 1,
                "allow_help_card": 1,
                "allow_share_draft": 1,
                "deduct_quota": 1,
                "status": 1,
                "sort_order": 20,
            },
            {
                "name": "高频加购包",
                "plan_type": "addon",
                "description": "用于少量高频用户补充主题会话额度。",
                "validity_days": 31,
                "monthly_topic_limit": 30,
                "enable_growth_profile": 0,
                "enable_periodic_reports": 0,
                "allow_help_card": 1,
                "allow_share_draft": 1,
                "deduct_quota": 1,
                "status": 1,
                "sort_order": 30,
            },
            {
                "name": "老师工作版",
                "plan_type": "teacher",
                "description": "内部老师使用，不消耗普通学员权益额度。",
                "validity_days": None,
                "monthly_topic_limit": None,
                "enable_growth_profile": 0,
                "enable_periodic_reports": 0,
                "allow_help_card": 1,
                "allow_share_draft": 1,
                "deduct_quota": 0,
                "status": 1,
                "sort_order": 40,
            },
        ],
    )
