# houtai/utils.py
import logging
import json
from functools import lru_cache
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Q
from rest_framework.response import Response
from .models import AbnormalUserLog, PlayerDailyStats, MerchantDailyStats, \
    ManagerRenewalDailyStats, ManagerDailyStats, LeaderDailyStats, WithdrawalDailyStats
from gvsdsdk.models import UserRole as SdkUserRole, RolePermission as SdkRolePermission, Permission as SdkPermission

from django.db import transaction
from django.db.models import F
from datetime import date
from decimal import Decimal

from gvsdsdk.fluent import db, func, FQ



logger = logging.getLogger(__name__)


def _club_id_for_yonghuid(yonghuid, club_id=None):
    from jituan.constants import CLUB_ID_DEFAULT
    from jituan.services.club_user import get_user_club_id
    from users.business_models import User
    if club_id:
        return club_id
    u = User.query.filter(UserUID=yonghuid).first()
    return get_user_club_id(u) if u else CLUB_ID_DEFAULT


def _get_real_ip(request):
    """获取真实IP（考虑代理）"""
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0].strip()
        return ip, x_forwarded_for
    else:
        ip = request.META.get('REMOTE_ADDR')
        return ip, ''


def _record_abnormal(account_id, request, attempt_type, detail=''):
    """记录异常操作（仅用于越权等攻击行为）"""
    try:
        real_ip, xff = _get_real_ip(request)
        headers = {k: v for k, v in request.META.items() if k.startswith('HTTP_')}
        headers_json = json.dumps(headers, ensure_ascii=False)[:2000]

        request_params = json.dumps(request.query_params.dict(), ensure_ascii=False) if request.query_params else ''
        request_body = request.body.decode('utf-8', errors='ignore')[:5000]

        AbnormalUserLog.query.create(
            account_id=account_id,
            ip_address=real_ip,
            real_ip=real_ip,
            x_forwarded_for=xff,
            user_agent=request.META.get('HTTP_USER_AGENT', ''),
            request_method=request.method,
            request_path=request.path,
            request_params=request_params,
            request_body=request_body,
            request_headers=headers_json,
            attempt_type=attempt_type,
            detail=detail,
        )
        logger.warning(f"记录异常用户: {account_id} IP:{real_ip} 类型:{attempt_type}")
    except Exception as e:
        logger.error(f"记录异常日志失败: {e}")


class _AllPermissions(list):
    """拥有 000001 超级管理权限时使用，使任何权限码 in 检查都返回 True"""
    def __contains__(self, item):
        return True


def has_perm_code(permissions, *codes):
    """权限码 in 检查；系统超管 _AllPermissions 视为全部通过。"""
    if isinstance(permissions, _AllPermissions):
        return True
    perms = permissions or []
    return any(c in perms for c in codes)


def has_club_super_perm(permissions):
    """本店超级管理 000001（含系统超管 _AllPermissions）。"""
    if isinstance(permissions, _AllPermissions):
        return True
    return '000001' in (permissions or [])


# 本店超管可直接使用的核心业务码（不必再绑集团权限）
CLUB_SUPER_IMPLIED_PERMS = frozenset({
    '002ab',  # 平台订单
    '002ac',  # 商家订单
    '003aa',  # 跨平台订单（只读/本店范围仍由 club 闸门控制）
    '005bb',  # 提现审核
})


def has_perm_code_or_club_super(permissions, *codes):
    """指定业务码，或本店超管 000001（对核心业务码生效）。"""
    if has_perm_code(permissions, *codes):
        return True
    if has_club_super_perm(permissions) and any(c in CLUB_SUPER_IMPLIED_PERMS for c in codes):
        return True
    return False


def has_merchant_order_permission(permissions):
    """商家/链接订单处理权限：002ac 商家订单、002ab 平台订单、003aa 跨平台；本店超管 000001 亦可。"""
    return has_perm_code_or_club_super(permissions, '002ac', '002ab', '003aa')


def has_platform_order_permission(permissions):
    """平台订单：002ab 或本店超管 000001。"""
    return has_perm_code_or_club_super(permissions, '002ab')


def _legacy_backend_role_permissions(phone):
    """
    读取旧权限表（backend.models）：
    user_role.account_id = 手机号 → role → role_permission → permission.perm_code
    与 gvsdsdk 表并行，未改 SDK 结构。
    """
    phone = (phone or '').strip()
    if not phone:
        return [], []
    try:
        from backend.models import (
            UserRole as LegacyUserRole,
            Role as BackendRole,
            Permission as BackendPermission,
        )
        role_ids = list(
            LegacyUserRole.objects.filter(account_id=phone).values_list('role_id', flat=True)
        )
        if not role_ids:
            return [], []
        perm_codes = list(
            BackendPermission.objects.filter(
                rolepermission__role_id__in=role_ids
            ).values_list('perm_code', flat=True).distinct()
        )
        role_names = list(
            BackendRole.objects.filter(role_id__in=role_ids).values_list('role_name', flat=True)
        )
        return perm_codes, role_names
    except Exception as e:
        logger.warning('legacy_backend_role_permissions phone=%s err=%s', phone, e)
        return [], []


def verify_kefu_permission(request, username_from_frontend=None):
    """
    验证客服/管理员身份，并返回该用户的所有权限列表（基于新RBAC表）
    只有前端传递的username与当前登录用户不匹配时，才记录异常并警告前端。

    参数:
        request: DRF request 对象
        username_from_frontend: 前端传递的账号（用于防越权）

    返回:
        (kefu_obj, permissions_list)   # 验证通过
        (None, Response)                # 验证失败，直接返回Response
    """
    current_user = request.user

    # ---------- 1. 必须是客服或管理员 ----------
    from jituan.constants import SUPER_ADMIN_PHONES
    from jituan.services.admin_context import (
        is_kefu_backend_account,
        is_kefu_account_disabled,
        is_hardcoded_super_phone,
        is_system_super_admin,
    )
    is_super_phone = is_hardcoded_super_phone(current_user)
    is_admin = current_user.UserType == 'admin' or current_user.IsSuperuser or is_super_phone

    # 已禁用客服：非白名单即使带 IsSuperuser 也不能继续调接口
    if is_kefu_account_disabled(current_user):
        return None, Response({'code': 403, 'msg': '客服账号已被禁用'}, status=403)

    if not is_kefu_backend_account(current_user):
        return None, Response({'code': 403, 'msg': '身份错误，非客服账号'}, status=403)

    # ---------- 2. 客服扩展表存在且状态正常（仅白名单超管可跳过） ----------
    kefu = None
    if is_admin and is_super_phone:
        from types import SimpleNamespace
        try:
            kefu = current_user.KefuProfile
        except ObjectDoesNotExist:
            kefu = SimpleNamespace(user=current_user)
    elif is_admin:
        # 非白名单「超管」仍必须客服状态正常
        try:
            kefu = current_user.KefuProfile
            if kefu.zhuangtai != 1:
                return None, Response({'code': 403, 'msg': '客服账号已被禁用'}, status=403)
        except ObjectDoesNotExist:
            from types import SimpleNamespace
            kefu = SimpleNamespace(user=current_user)
    else:
        try:
            kefu = current_user.KefuProfile
            if kefu.zhuangtai != 1:
                return None, Response({'code': 403, 'msg': '客服账号已被禁用'}, status=403)
        except ObjectDoesNotExist:
            return None, Response({'code': 403, 'msg': '客服账号不存在'}, status=403)

    # ---------- 3. 越权检测（只记录前端篡改username的情况） ----------
    if username_from_frontend and current_user.Phone != username_from_frontend:
        detail = f'前端username: {username_from_frontend}，实际登录账号: {current_user.Phone}'
        _record_abnormal(current_user.Phone, request, '越权尝试篡改username', detail=detail)
        return None, Response({
            'code': 403,
            'msg': '身份错误，无权操作其他账号，相关操作已记录'
        }, status=403)

    # ---------- 4. 获取用户的所有权限（与菜单 menu-access 同一套算法） ----------
    from jituan.constants import CLUB_ID_DEFAULT, DATA_SCOPE_SINGLE
    from jituan.services.admin_context import resolve_admin_effective_club, get_allowed_club_ids, is_system_super_admin
    from jituan.services.club_rbac import resolve_effective_permission_codes

    eff_club = getattr(request, 'club_id', None) or CLUB_ID_DEFAULT
    eff_scope = getattr(request, 'club_scope', None) or DATA_SCOPE_SINGLE
    allowed_club_ids = None
    if not is_system_super_admin(current_user):
        eff_club, eff_scope, club_err = resolve_admin_effective_club(current_user, request)
        if club_err:
            return None, Response({'code': 403, 'msg': club_err}, status=403)
        request.club_id = eff_club
        request.club_scope = eff_scope
        allowed_club_ids = list(get_allowed_club_ids(current_user))

    try:
        if is_system_super_admin(current_user):
            user_uuid = current_user.UserUUID
            role_uuids = list(SdkUserRole.objects.filter(
                UserUUID=user_uuid
            ).values_list('RoleUUID', flat=True))
            if role_uuids:
                perm_uuids = list(SdkRolePermission.objects.filter(
                    RoleUUID__in=role_uuids
                ).values_list('PermUUID', flat=True))
                permissions = list(SdkPermission.objects.filter(
                    PermUUID__in=perm_uuids, PermStatus=1
                ).values_list('PermCode', flat=True).distinct())
            else:
                permissions = []
            legacy_codes, _ = _legacy_backend_role_permissions(current_user.Phone)
            if legacy_codes:
                permissions = list(set(list(permissions) + legacy_codes))
        else:
            permissions = resolve_effective_permission_codes(
                current_user, eff_club, eff_scope, allowed_club_ids,
            )
    except Exception as e:
        logger.warning(
            'verify_kefu_permission failed: UserUUID=%s Phone=%s err=%s',
            getattr(current_user, 'UserUUID', None),
            getattr(current_user, 'Phone', None),
            e,
            exc_info=True,
        )
        permissions = []

    # 仅系统级超管自动拥有全部功能权限；俱乐部 000001 只解锁超管页，不展开全部菜单
    if is_system_super_admin(current_user):
        if '000001' not in permissions:
            permissions.insert(0, '000001')
        permissions = _AllPermissions(permissions)

    if not permissions:
        logger.warning(f"用户 {current_user.Phone} 没有任何权限，请检查角色分配")

    return kefu, permissions





def update_dashou_daily_by_action(yonghuid, amount, action, club_id=None):
    """
    根据行为类型更新打手每日统计（接单、成交、退款）
    """
    amount = Decimal(str(amount)) if amount else Decimal('0.00')
    if amount <= 0:
        return

    cid = _club_id_for_yonghuid(yonghuid, club_id)
    today = date.today()

    with transaction.atomic():
        stat, created = PlayerDailyStats.objects.select_for_update().get_or_create(
            club_id=cid,
            PlayerID=yonghuid,
            Date=today,
            defaults={
                'club_id': cid,
                'PlayerID': yonghuid,
                'Date': today,
                'AcceptedOrderTotal': 0,
                'AcceptedAmount': Decimal('0.00'),
                'CompletedOrderTotal': 0,
                'CompletedAmount': Decimal('0.00'),
                'RefundCount': 0,
                'RefundAmount': Decimal('0.00'),
            }
        )

        update_fields = {}
        if action == 1:  # 接单
            update_fields['AcceptedOrderTotal'] = F('AcceptedOrderTotal') + 1
            update_fields['AcceptedAmount'] = F('AcceptedAmount') + amount
        elif action == 2:  # 成交
            update_fields['CompletedOrderTotal'] = F('CompletedOrderTotal') + 1
            update_fields['CompletedAmount'] = F('CompletedAmount') + amount
        elif action == 3:  # 退款
            update_fields['RefundCount'] = F('RefundCount') + 1
            update_fields['RefundAmount'] = F('RefundAmount') + amount
        else:
            return  # 无效行为

        if update_fields:
            PlayerDailyStats.query.filter(id=stat.id).update(**update_fields)


def update_shangjia_daily(yonghuid, amount, action, order_id=None, club_id=None):
    """
    根据操作行为更新商家每日统计（派发、结算、退款）
    """
    amount = Decimal(str(amount)) if amount else Decimal('0.00')
    if amount <= 0:
        return

    cid = _club_id_for_yonghuid(yonghuid, club_id)
    today = date.today()

    with transaction.atomic():
        stat, created = MerchantDailyStats.objects.select_for_update().get_or_create(
            club_id=cid,
            MerchantID=yonghuid,
            Date=today,
            defaults={
                'club_id': cid,
                'MerchantID': yonghuid,
                'Date': today,
                'AssignedOrderCount': 0,
                'AssignedAmount': Decimal('0.00'),
                'SettledOrderCount': 0,
                'SettledAmount': Decimal('0.00'),
                'RefundOrderCount': 0,
                'RefundAmount': Decimal('0.00'),
            }
        )

        # 构建本次更新的字段，使用 F 表达式进行原子累加
        update_fields = {}
        if action == 1:  # 派发
            update_fields['AssignedOrderCount'] = F('AssignedOrderCount') + 1
            update_fields['AssignedAmount'] = F('AssignedAmount') + amount
        elif action == 2:  # 结算（成交）
            update_fields['SettledOrderCount'] = F('SettledOrderCount') + 1
            update_fields['SettledAmount'] = F('SettledAmount') + amount
        elif action == 3:  # 退款
            update_fields['RefundOrderCount'] = F('RefundOrderCount') + 1
            update_fields['RefundAmount'] = F('RefundAmount') + amount
        else:
            # 无效的行为类型，直接返回
            return

        # 执行原子更新
        MerchantDailyStats.query.filter(id=stat.id).update(**update_fields)

    if order_id:
        try:
            from merchant_ops.services.stats import sync_staff_stats_by_order_id
            sync_staff_stats_by_order_id(order_id, amount, action)
        except Exception:
            logger.warning('同步客服日统计失败 order_id=%s', order_id, exc_info=True)


def update_guanshi_daily_by_action(yonghuid, action, amount=Decimal('0.00'), club_id=None):
    """
    根据操作行为更新管事每日统计（邀请打手、充值会员、订单/押金分红）
    """
    cid = _club_id_for_yonghuid(yonghuid, club_id)
    today = date.today()

    with transaction.atomic():
        stat, created = ManagerDailyStats.objects.select_for_update().get_or_create(
            club_id=cid,
            ManagerID=yonghuid,
            Date=today,
            defaults={
                'club_id': cid,
                'ManagerID': yonghuid,
                'Date': today,
                'InvitedPlayerCount': 0,
                'RechargedPlayerCount': 0,
                'TotalIncome': Decimal('0.00'),
            }
        )

        if action == 1:
            # 邀请打手：无论新创建还是已存在，直接 +1
            if created:
                stat.InvitedPlayerCount = 1
                stat.save()
            else:
                ManagerDailyStats.query.filter(id=stat.id).update(
                    InvitedPlayerCount=F('InvitedPlayerCount') + 1
                )

        elif action == 2:
            amount = Decimal(str(amount)) if amount else Decimal('0.00')
            if amount <= 0:
                return
            if created:
                stat.RechargedPlayerCount = 1
                stat.TotalIncome = amount
                stat.save()
            else:
                ManagerDailyStats.query.filter(id=stat.id).update(
                    RechargedPlayerCount=F('RechargedPlayerCount') + 1,
                    TotalIncome=F('TotalIncome') + amount
                )

        elif action in (3, 4):
            amount = Decimal(str(amount)) if amount else Decimal('0.00')
            if amount <= 0:
                return
            if created:
                stat.TotalIncome = amount
                stat.save()
            else:
                ManagerDailyStats.query.filter(id=stat.id).update(
                    TotalIncome=F('TotalIncome') + amount
                )


def update_guanshi_xufei_daily(yonghuid, xufei_jine=Decimal('0.00'), club_id=None):
    """管事续费统计（单独表）"""
    cid = _club_id_for_yonghuid(yonghuid, club_id)
    today = date.today()
    with transaction.atomic():
        stat, created = ManagerRenewalDailyStats.objects.select_for_update().get_or_create(
            club_id=cid,
            ManagerID=yonghuid,
            Date=today,
            defaults={
                'club_id': cid,
                'ManagerID': yonghuid,
                'Date': today,
                'RenewalTotal': 1,
                'RenewalRevenue': xufei_jine,
            }
        )
        if not created:
            ManagerRenewalDailyStats.query.filter(id=stat.id).update(
                RenewalTotal=F('RenewalTotal') + 1,
                RenewalRevenue=F('RenewalRevenue') + xufei_jine
            )


def update_zuzhang_daily_by_action(yonghuid, action, amount=Decimal('0.00'), club_id=None):
    """根据操作行为更新组长每日统计"""
    cid = _club_id_for_yonghuid(yonghuid, club_id)
    today = date.today()

    with transaction.atomic():
        stat, created = LeaderDailyStats.objects.select_for_update().get_or_create(
            club_id=cid,
            LeaderID=yonghuid,
            Date=today,
            defaults={
                'club_id': cid,
                'LeaderID': yonghuid,
                'Date': today,
                'InvitedManagerCount': 0,
                'TotalIncome': Decimal('0.00'),
                'CommissionAmount': Decimal('0.00'),
            }
        )

        if created:
            # 新记录直接设置初始值
            if action == 1:
                stat.InvitedManagerCount = 1
            elif action == 2:
                amount = Decimal(str(amount)) if amount else Decimal('0.00')
                stat.TotalIncome = amount
                stat.CommissionAmount = amount
            stat.save()
        else:
            # 已存在记录，使用 F 表达式原子累加
            if action == 1:
                LeaderDailyStats.query.filter(id=stat.id).update(
                    InvitedManagerCount=F('InvitedManagerCount') + 1
                )
            elif action == 2:
                amount = Decimal(str(amount)) if amount else Decimal('0.00')
                if amount > 0:
                    LeaderDailyStats.query.filter(id=stat.id).update(
                        TotalIncome=F('TotalIncome') + amount,
                        CommissionAmount=F('CommissionAmount') + amount
                    )



def update_tixian_daily_stat(leixing, amount, club_id=None):
    """
    更新每日提现统计（平台维度，按俱乐部）
    leixing: 1=打手, 2=管事, 3=组长
    amount: 本次提现金额（申请金额，含手续费）
    """
    from jituan.constants import CLUB_ID_DEFAULT
    from jituan.services.withdraw_config import get_or_create_platform_daily_stat

    club_id = (club_id or '').strip() or CLUB_ID_DEFAULT
    today = date.today()
    with transaction.atomic():
        stat = get_or_create_platform_daily_stat(club_id, leixing, today)
        WithdrawalDailyStats.query.filter(id=stat.id).update(
            total_amount=F('total_amount') + amount
        )


# 罚款权限（与 permission 表一致）
# 66693a/b/c + 66694c：按身份管理罚款；99933abs：罚款申请（通用，可查看列表并操作各身份）
_DEFAULT_FADAN_PERM_TO_SHENFEN = {
    '66693a': 1,   # 罚款管理-打手
    '66693c': 2,   # 罚款管理-管事
    '66693b': 3,   # 罚款管理-商家
    '66694c': 4,   # 罚款管理-组长
}

_FADAN_GENERIC_PERMS = (
    '99933abs',    # 罚款申请权限
)

_SHENFEN_KEYWORDS = {
    '打手': 1,
    '管事': 2,
    '商家': 3,
    '组长': 4,
}

SHENFEN_PROFILE_MAP = {
    1: 'DashouProfile',
    2: 'GuanshiProfile',
    3: 'ShopProfile',
    4: 'ZuzhangProfile',
}


@lru_cache(maxsize=1)
def _get_fadan_permission_config():
    """
    加载罚款相关权限码（硬编码 + permission 表按 perm_name 补充）。
    仅匹配 perm_name 含「罚款/罚单」，避免 qtczcaiwu 等描述里带「罚款」的财务权限误入。
    """
    perm_map = dict(_DEFAULT_FADAN_PERM_TO_SHENFEN)
    generic_codes = list(_FADAN_GENERIC_PERMS)
    try:
        rows = Permission.query.filter(
            Q(perm_name__icontains='罚款') | Q(perm_name__icontains='罚单')
        ).values('perm_code', 'perm_name')
        for row in rows:
            code = row['perm_code']
            name = row['perm_name'] or ''
            matched_sf = None
            for kw, sf in _SHENFEN_KEYWORDS.items():
                if kw in name:
                    matched_sf = sf
                    break
            if matched_sf is not None:
                perm_map[code] = matched_sf
            elif code not in generic_codes:
                generic_codes.append(code)
    except Exception as e:
        logger.warning(f"从 permission 表加载罚款权限失败，使用硬编码映射: {e}")
    return perm_map, tuple(generic_codes)


# 兼容旧引用
PERMISSION_TO_SHENFEN = _DEFAULT_FADAN_PERM_TO_SHENFEN


def has_fadan_view_permission(permissions, account_id=''):
    """列表/统计：拥有任一罚款权限或超级管理员权限即可查看。"""
    if '000001' in permissions:
        return True
    perm_map, generic_codes = _get_fadan_permission_config()
    all_codes = set(perm_map.keys()) | set(generic_codes)
    if any(p in permissions for p in all_codes):
        return True
    logger.warning(
        f"罚款查看权限不足 account={account_id} "
        f"user_perms={permissions} need_any={sorted(all_codes)}"
    )
    return False


def check_fadan_permission(permissions, shenfen):
    """创建/处理：需拥有对应身份的罚款权限，或通用罚款权限，或超级管理员权限。"""
    if '000001' in permissions:
        return True
    if any(p in permissions for p in _get_fadan_permission_config()[1]):
        return True
    shenfen = int(shenfen)
    perm_map, _ = _get_fadan_permission_config()
    for perm, sf in perm_map.items():
        if sf == shenfen and perm in permissions:
            return True
    return False


def fmt_datetime(dt):
    """格式化时间为前端通用字符串。"""
    if not dt:
        return ''
    return dt.strftime('%Y-%m-%d %H:%M:%S')


def datetime_aliases(dt):
    """同时返回 CreateTime / create_time，避免前后端字段名不一致。"""
    s = fmt_datetime(dt)
    return {'CreateTime': s, 'create_time': s}


def pick_order_id(data):
    """兼容前端 dingdan_id 与 SDK 字段 OrderID。"""
    return str(data.get('OrderID') or data.get('dingdan_id') or '').strip()


def pick_leixing_id(data):
    """兼容前端 leixing_id 与 SDK 字段 ProductTypeID。"""
    val = data.get('leixing_id')
    if val is None or val == '':
        val = data.get('ProductTypeID')
    if val is None or val == '':
        return None
    try:
        return int(val)
    except (ValueError, TypeError):
        return None


def pick_penalty_create_params(data):
    """兼容罚单创建：SDK 字段名与旧版拼音字段名。"""
    penalized_id = str(data.get('PenalizedUserID') or data.get('beichufa_id') or '').strip()
    reason = str(data.get('Reason') or data.get('chufaliyou') or '').strip()
    fine_amount = data.get('FineAmount')
    if fine_amount is None:
        fine_amount = data.get('fakuanjine')
    affects = data.get('AffectsGrabbing')
    if affects is None:
        affects = data.get('yingxiang_qiangdan', 1)
    return penalized_id, reason, fine_amount, affects


# ---------- 修改记录（Xiugaijilu） ----------
XIUGAI_LEIXING_DASHOU = 2
XIUGAI_LEIXING_GUANSHI = 3
XIUGAI_LEIXING_SHANGJIA = 4
XIUGAI_LEIXING_ZUZHANG = 5

XIUGAI_LEIXING_LABEL = {
    XIUGAI_LEIXING_DASHOU: '打手',
    XIUGAI_LEIXING_GUANSHI: '管事',
    XIUGAI_LEIXING_SHANGJIA: '商家',
    XIUGAI_LEIXING_ZUZHANG: '组长',
}


def write_xiugai_log(*, yonghuid, xiugaiid, leixing, qitashuoming, club_id=None, request_ip='', **extra_fields):
    """
    统一写入 xiugaijilu 修改记录。
    qitashuoming 应详细描述本次操作（尤其是金额、身份、上下级变更等）。
    extra_fields 可传入 xiugaitijiao、shangjiayue、guanshiyue 等模型字段。
    """
    from users.models import Xiugaijilu
    from jituan.services.admin_audit import log_admin_audit_from_xiugai

    if not qitashuoming:
        label = XIUGAI_LEIXING_LABEL.get(leixing, f'类型{leixing}')
        qitashuoming = f'【后台】修改{label}信息，操作人{xiugaiid}'

    Xiugaijilu.query.create(
        yonghuid=str(yonghuid),
        xiugaiid=str(xiugaiid),
        leixing=leixing,
        qitashuoming=qitashuoming,
        **extra_fields,
    )
    log_admin_audit_from_xiugai(
        yonghuid=yonghuid,
        xiugaiid=xiugaiid,
        leixing=leixing,
        qitashuoming=qitashuoming,
        club_id=club_id,
        request_ip=request_ip,
    )