"""payment plugin fields

Revision ID: 069_payment_plugins
Revises: 068_verification_plugin_rules
Create Date: 2026-06-23
"""

from alembic import op
import sqlalchemy as sa


revision = "069_payment_plugins"
down_revision = "068_verification_plugin_rules"
branch_labels = None
depends_on = None


def _table_exists(bind: sa.engine.Connection, table_name: str) -> bool:
    return table_name in set(sa.inspect(bind).get_table_names())


def _column_names(bind: sa.engine.Connection, table_name: str) -> set[str]:
    return {column["name"] for column in sa.inspect(bind).get_columns(table_name)}


def _index_names(bind: sa.engine.Connection, table_name: str) -> set[str]:
    return {index["name"] for index in sa.inspect(bind).get_indexes(table_name)}


def _upgrade_channel_enum(bind: sa.engine.Connection) -> None:
    if bind.dialect.name == "mysql":
        op.execute("ALTER TABLE recharge_orders MODIFY channel ENUM('alipay','wxpay','qqpay','admin') NOT NULL")


def _downgrade_channel_enum(bind: sa.engine.Connection) -> None:
    if bind.dialect.name == "mysql":
        op.execute("UPDATE recharge_orders SET channel='alipay' WHERE channel='qqpay'")
        op.execute("ALTER TABLE recharge_orders MODIFY channel ENUM('alipay','wxpay','admin') NOT NULL")


def upgrade() -> None:
    bind = op.get_bind()
    if not _table_exists(bind, "recharge_orders"):
        return

    _upgrade_channel_enum(bind)
    columns = _column_names(bind, "recharge_orders")
    indexes = _index_names(bind, "recharge_orders")

    if "payment_plugin" not in columns:
        op.add_column("recharge_orders", sa.Column("payment_plugin", sa.String(80), nullable=True))
    if "payment_method" not in columns:
        op.add_column("recharge_orders", sa.Column("payment_method", sa.String(32), nullable=True))
    if "notify_token" not in columns:
        op.add_column("recharge_orders", sa.Column("notify_token", sa.String(128), nullable=True))

    indexes = _index_names(bind, "recharge_orders")
    if "ix_recharge_orders_payment_plugin" not in indexes:
        op.create_index("ix_recharge_orders_payment_plugin", "recharge_orders", ["payment_plugin"])
    if "ix_recharge_orders_payment_method" not in indexes:
        op.create_index("ix_recharge_orders_payment_method", "recharge_orders", ["payment_method"])
    if "ix_recharge_orders_notify_token" not in indexes:
        op.create_index("ix_recharge_orders_notify_token", "recharge_orders", ["notify_token"])

    op.execute(
        "UPDATE recharge_orders "
        "SET payment_plugin = COALESCE(payment_plugin, 'epay_alipay'), "
        "payment_method = COALESCE(payment_method, channel) "
        "WHERE payment_plugin IS NULL OR payment_method IS NULL"
    )


def downgrade() -> None:
    bind = op.get_bind()
    if not _table_exists(bind, "recharge_orders"):
        return

    indexes = _index_names(bind, "recharge_orders")
    for index_name in (
        "ix_recharge_orders_notify_token",
        "ix_recharge_orders_payment_method",
        "ix_recharge_orders_payment_plugin",
    ):
        if index_name in indexes:
            op.drop_index(index_name, table_name="recharge_orders")

    columns = _column_names(bind, "recharge_orders")
    for column in ("notify_token", "payment_method", "payment_plugin"):
        if column in columns:
            op.drop_column("recharge_orders", column)

    _downgrade_channel_enum(bind)

