import hmac
import threading
import traceback
import uuid
import hashlib
import xmltodict
import time
import logging
import requests
import os
import secrets
import random
import string
from calendar import monthrange
from decimal import Decimal
from datetime import date, datetime, timedelta
from django.utils import timezone
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
from django.core.paginator import Paginator
from django.db import models, transaction, IntegrityError
from django.db.models import Q, Count, Sum, F, Exists, OuterRef
from gvsdsdk.fluent import db, func, FQ
from django.db.models.functions import TruncDate, TruncMonth, TruncYear
from django.contrib.auth.hashers import make_password
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework.parsers import JSONParser, MultiPartParser, FormParser

# 工具类导入
from utils.oss_utils import validate_image, upload_to_oss, delete_from_oss
from backend.utils import (
    update_dashou_daily_by_action,
    update_shangjia_daily
)
from jituan.services.club_context import filter_club_char_field, filter_queryset_by_club, filter_user_related_by_club, filter_user_qs_by_club, orders_for_request
from jituan.services.catalog_scope import block_non_group_catalog_scope
from jituan.services.club_penalty import (
    filter_penalty_qs, resolve_penalty_club_id, filter_gsfenhong_qs,
    forbid_penalty_out_of_scope, resolve_penalty_record_club_id,
)
from jituan.services.club_user_access import forbid_if_user_out_of_scope, list_response_meta
from shop.utils import update_dianpu_daily_stat
from products.utils import update_shangpin_daily_stat
from orders.notice_tasks import dingdan_guangbo
from ..utils import (
    verify_kefu_permission,
    PERMISSION_TO_SHENFEN,
    SHENFEN_PROFILE_MAP,
    has_fadan_view_permission,
    has_merchant_order_permission,
    check_fadan_permission,
    pick_order_id,
    pick_penalty_create_params,
    write_xiugai_log,
    XIUGAI_LEIXING_DASHOU,
    XIUGAI_LEIXING_GUANSHI,
    XIUGAI_LEIXING_SHANGJIA,
    XIUGAI_LEIXING_ZUZHANG,
    XIUGAI_LEIXING_LABEL,
)

# models 集中导入
## gvsdsdk RBAC 模型（使用 PascalCase 字段名，匹配实际数据库表结构）
from gvsdsdk.models import Role, Permission, RolePermission, UserRole
## backend
from backend.models import WithdrawalDailyStats

## users
from users.models import (
    UserGuanshi, UserBoss, UserZuzhang,
    UserKefu, UserDashou, Xiugaijilu, UserShangjia, UserShenheguan
)
from users.business_models import User

## orders
from orders.models import (
    CommissionRate, PlayerDeliveryImage, PenaltyRecord,
    OrderPlayerHistory, Order, RefundRecord,
    MerchantOrderExt, Penalty, PenaltyAppealImage, PenaltyBonus
)

## shop
from shop.models import Dianpu, DianpuMorenPeizhi, YonghuPingzheng, ShangpinLeixingDianpu, DianpuShangpinShenheShezhi

## products
from products.models import (
    Shangpin, ShangpinLeixing, ShangpinZhuanqu, Huiyuan,
    DuociFenhong, Czjilu, Huiyuangoumai, Gsfenhong
)

## config
from config.models import (
    WithdrawConfig, ShangjiaLianjie, AccountPermission,
    TixianQuotaDefault,
    DailyIncomeStat, DailyPayoutStat, PopupPage, PopupConfig, PopupImage
)

## rank
from rank.models import (
    KaoheguanBankuai, Bankuai, Chenghao, KaoheCishuFeiyong,
    YonghuChenghao, ShenheJilu, KaoheJiluFeiyong, KaoheJujueJilu
)

# 序列化器
from ..serializers import PopupPageSerializer

# 全局常量、日志对象
logger = logging.getLogger('houtai')
SHOP_PRODUCT_PERMS = ['1199ab', '1199abc', '1199abd']

# 审核记录状态映射（原位于 zxkf.py，按功能组归类到考核模块）
SHENHE_ZHUANGTAI_MAP = {
    0: '考核中',
    1: '已通过',
    2: '未通过',
    3: '待审核',
}

class KhgglView(APIView):
    """
    考核官管理数据接口（列表、筛选、分页）
    POST /houtai/khggl
    Body: {
        "phone": "管理员手机号",
        "page": 1,                 // 可选，默认1
        "page_size": 15,           // 可选，默认15
        "yonghuid": "1234567",     // 按用户ID筛选，可选
        "zhuangtai": 1,           // 账号状态 0=禁用,1=正常，可选
        "shenhe_zhuangtai": 0,    // 审核官状态 0=空闲,1=审核中，可选
        "bankuai_name": "王者"     // 板块名称模糊筛选，可选
    }
    """
    permission_classes = [IsAuthenticated]

    def post(self, request):
        try:
            username_from_frontend = request.data.get('phone', None)
            kefu_obj, permissions = verify_kefu_permission(request, username_from_frontend)
            if kefu_obj is None:
                return permissions

            if 'kaohepeizhi' not in permissions:
                return Response({'code': 403, 'msg': '无考核管理权限'}, status=403)

            # 分页参数
            page = int(request.data.get('page', 1))
            page_size = int(request.data.get('page_size', 15))
            if page < 1: page = 1
            if page_size < 1: page_size = 15

            # 筛选条件
            filter_yonghuid = request.data.get('yonghuid', '').strip()
            filter_zhuangtai = request.data.get('zhuangtai')
            filter_shenhe_zhuangtai = request.data.get('shenhe_zhuangtai')
            filter_bankuai_name = request.data.get('bankuai_name', '').strip()

            # 基础查询：所有审核官，预加载用户及打手扩展表
            queryset = filter_user_related_by_club(
                UserShenheguan.query.select_related('user__DashouProfile'),
                request,
            )

            if filter_yonghuid:
                queryset = queryset.filter(user__UserUID=filter_yonghuid)
            if filter_zhuangtai is not None:
                queryset = queryset.filter(zhuangtai=filter_zhuangtai)
            if filter_shenhe_zhuangtai is not None:
                queryset = queryset.filter(shenhe_zhuangtai=filter_shenhe_zhuangtai)

            # 如果填写了板块名称，筛选出关联该板块的审核官
            if filter_bankuai_name:
                bankuai_ids = Bankuai.query.filter(
                    mingcheng__icontains=filter_bankuai_name
                ).values_list('bankuai_id', flat=True)
                shenheguan_ids = KaoheguanBankuai.query.filter(
                    bankuai_id__in=bankuai_ids
                ).values_list('kaoheguan_id', flat=True)
                queryset = queryset.filter(user__UserUID__in=shenheguan_ids)

            total = queryset.count()
            start = (page - 1) * page_size
            end = start + page_size
            shenheguan_list = queryset.order_by('-CreateTime')[start:end]

            from collections import defaultdict
            from jituan.services.shenhe_club import yonghu_chenghao_qs_for_request

            # ---------- 优化：板块打手数量（1 次 annotate 替代 2N 次循环查询）----------
            # 原逻辑：每板块查 dashou 标签 ID，再统计关联的不同用户数（要求有 DashouProfile）
            bankuai_dashou_qs = yonghu_chenghao_qs_for_request(
                YonghuChenghao.query.filter(
                    chenghao__leixing='dashou',
                    yonghu__DashouProfile__isnull=False,
                ),
                request,
            )
            bankuai_dashou_count_map = {
                item['chenghao__bankuai_id']: item['user_count']
                for item in bankuai_dashou_qs.values('chenghao__bankuai_id').annotate(
                    user_count=Count('yonghu', distinct=True)
                )
            }

            # ---------- 优化：板块标签统计（1 次 annotate 替代 N*M 次循环查询）----------
            # 原逻辑：每板块每标签分别统计关联的不同用户数（不要求 DashouProfile）
            tag_counts_qs = yonghu_chenghao_qs_for_request(
                YonghuChenghao.query.filter(chenghao__leixing='dashou'),
                request,
            ).values(
                'chenghao_id', 'chenghao__bankuai_id', 'chenghao__mingcheng'
            ).annotate(user_count=Count('yonghu', distinct=True))

            tags_by_bankuai = defaultdict(list)
            for item in tag_counts_qs:
                tags_by_bankuai[item['chenghao__bankuai_id']].append({
                    'id': item['chenghao_id'],
                    'name': item['chenghao__mingcheng'],
                    'user_count': item['user_count'],
                })

            all_banquai = Bankuai.query.all()
            bankuai_tags_data = [
                {
                    'bankuai_id': bk.bankuai_id,
                    'mingcheng': bk.mingcheng,
                    'tags': tags_by_bankuai.get(bk.bankuai_id, []),
                }
                for bk in all_banquai
            ]

            # ---------- 优化：审核官板块关联（1 次批量查询替代 P 次循环查询）----------
            shenheguan_user_uids = [sg.user.UserUID for sg in shenheguan_list]
            all_kgs = KaoheguanBankuai.query.filter(
                kaoheguan_id__in=shenheguan_user_uids
            ).select_related('bankuai')
            kg_map = defaultdict(list)
            for kg in all_kgs:
                kg_map[kg.kaoheguan_id].append(kg)

            # 构造返回数据（审核官列表）
            data_list = []
            for sg in shenheguan_list:
                user = sg.user
                bankuai_info = [
                    {
                        'bankuai_id': kg.bankuai.bankuai_id,
                        'mingcheng': kg.bankuai.mingcheng,
                        'dashou_count': bankuai_dashou_count_map.get(kg.bankuai.bankuai_id, 0),
                    }
                    for kg in kg_map.get(user.UserUID, [])
                ]

                dashou_nick = user.DashouProfile.nicheng if hasattr(user, 'DashouProfile') and user.DashouProfile else ''

                data_list.append({
                    'yonghuid': user.UserUID,
                    'avatar': user.Avatar or '',
                    'phone': user.Phone or '',
                    'zhuangtai': sg.zhuangtai,
                    'shenhe_zhuangtai': sg.shenhe_zhuangtai,
                    'shenhe_zongshu': sg.shenhe_zongshu,
                    'tongguo_zongshu': sg.tongguo_zongshu,
                    'yue': float(sg.yue),
                    'zonge': float(sg.zonge),
                    'CreateTime': sg.CreateTime.strftime('%Y-%m-%d %H:%M:%S') if sg.CreateTime else '',
                    'UpdateTime': sg.UpdateTime.strftime('%Y-%m-%d %H:%M:%S') if sg.UpdateTime else '',
                    'bankuai': bankuai_info,
                    'nicheng': dashou_nick,
                    'is_renzheng': sg.is_renzheng,
                })

            all_bankuai = list(Bankuai.query.values('bankuai_id', 'mingcheng'))

            return Response({
                'code': 0,
                'msg': 'ok',
                'data': {
                    'total': total,
                    'page': page,
                    'page_size': page_size,
                    'list': data_list,
                    'all_bankuai': all_bankuai,
                    'bankuai_tags': bankuai_tags_data,   # 新增板块标签统计
                }
            })

        except Exception as e:
            logger.exception("KhgglView 接口错误")
            return Response({'code': 1, 'msg': f'服务器内部错误: {str(e)}'}, status=500)

class ShgxgsjView(APIView):
    """
    审核官信息修改（余额、状态、板块关联）
    POST /houtai/shgxgsj
    """
    permission_classes = [IsAuthenticated]

    def post(self, request):
        try:
            username_from_frontend = request.data.get('phone', None)
            kefu_obj, permissions = verify_kefu_permission(request, username_from_frontend)
            if kefu_obj is None:
                return permissions
            if 'kaohepeizhi' not in permissions:
                return Response({'code': 403, 'msg': '无考核管理权限'}, status=403)

            yonghuid = request.data.get('yonghuid')
            if not yonghuid:
                return Response({'code': 1, 'msg': '缺少用户ID'}, status=400)

            try:
                shenheguan = UserShenheguan.query.select_related('user').get(user__UserUID=yonghuid)
            except UserShenheguan.DoesNotExist:
                return Response({'code': 1, 'msg': '审核官不存在'}, status=404)

            from jituan.services.shenhe_club import user_belongs_to_request_club
            if not user_belongs_to_request_club(shenheguan.user, request):
                return Response({'code': 403, 'msg': '该考核官不属于当前俱乐部'}, status=403)

            action = request.data.get('action')

            if action == 'update_info':
                if 'yue' in request.data:
                    shenheguan.yue = float(request.data.get('yue', 0))
                if 'zhuangtai' in request.data:
                    zt = int(request.data.get('zhuangtai'))
                    if zt not in [0, 1]:
                        return Response({'code': 1, 'msg': '无效的账号状态'}, status=400)
                    shenheguan.zhuangtai = zt
                if 'shenhe_zhuangtai' in request.data:
                    szt = int(request.data.get('shenhe_zhuangtai'))
                    if szt not in [0, 1]:
                        return Response({'code': 1, 'msg': '无效的审核官状态'}, status=400)
                    shenheguan.shenhe_zhuangtai = szt
                # 新增认证状态编辑
                if 'is_renzheng' in request.data:
                    shenheguan.is_renzheng = bool(request.data.get('is_renzheng'))
                shenheguan.save()
                return Response({'code': 0, 'msg': '修改成功'})

            elif action == 'add_bankuai':
                bankuai_id = request.data.get('bankuai_id')
                if not bankuai_id:
                    return Response({'code': 1, 'msg': '缺少板块ID'}, status=400)
                if not Bankuai.query.filter(bankuai_id=bankuai_id).exists():
                    return Response({'code': 1, 'msg': '板块不存在'}, status=400)
                if KaoheguanBankuai.query.filter(kaoheguan_id=yonghuid, bankuai_id=bankuai_id).exists():
                    return Response({'code': 1, 'msg': '已关联该板块'}, status=400)
                KaoheguanBankuai.query.create(kaoheguan_id=yonghuid, bankuai_id=bankuai_id)
                return Response({'code': 0, 'msg': '板块关联成功'})

            elif action == 'remove_bankuai':
                bankuai_id = request.data.get('bankuai_id')
                if not bankuai_id:
                    return Response({'code': 1, 'msg': '缺少板块ID'}, status=400)
                deleted, _ = KaoheguanBankuai.query.filter(
                    kaoheguan_id=yonghuid, bankuai_id=bankuai_id
                ).delete()
                if not deleted:
                    return Response({'code': 1, 'msg': '未找到该板块关联'}, status=400)
                return Response({'code': 0, 'msg': '板块移除成功'})

            else:
                return Response({'code': 1, 'msg': '未知操作'}, status=400)

        except Exception as e:
            logger.exception("ShgxgsjView 接口错误")
            return Response({'code': 1, 'msg': f'服务器内部错误: {str(e)}'}, status=500)





def _batch_user_profile_map(user_uids):
    """批量获取用户头像、昵称、手机号"""
    uids = list({u for u in user_uids if u})
    if not uids:
        return {}
    users = User.query.filter(UserUID__in=uids)
    dashou_nicks = {
        d.user.UserUID: d.nicheng
        for d in UserDashou.query.filter(user__UserUID__in=uids).select_related('user')
    }
    result = {}
    for u in users:
        result[u.UserUID] = {
            'yonghuid': u.UserUID,
            'avatar': u.Avatar or '',
            'phone': u.Phone or '',
            'nicheng': dashou_nicks.get(u.UserUID) or u.UserName or u.Phone or u.UserUID,
        }
    return result


def _build_shenhe_jilu_filters(request_data):
    """构造 ShenheJilu 查询条件（列表与统计共用）"""
    qs = ShenheJilu.query.select_related('bankuai', 'chenghao')

    jilu_id = (request_data.get('jilu_id') or '').strip()
    if jilu_id:
        qs = qs.filter(jilu_id=jilu_id)

    zhuangtai = request_data.get('zhuangtai')
    if zhuangtai is not None and zhuangtai != '':
        qs = qs.filter(zhuangtai=int(zhuangtai))

    assessed = request_data.get('assessed')
    if assessed == 'done':
        qs = qs.filter(zhuangtai__in=[1, 2])
    elif assessed == 'undone':
        qs = qs.filter(zhuangtai__in=[0, 3])

    bankuai_id = request_data.get('bankuai_id')
    if bankuai_id not in (None, ''):
        qs = qs.filter(bankuai_id=int(bankuai_id))

    chenghao_id = request_data.get('chenghao_id')
    if chenghao_id not in (None, ''):
        qs = qs.filter(chenghao_id=int(chenghao_id))

    cishu = request_data.get('cishu')
    if cishu not in (None, ''):
        qs = qs.filter(cishu=int(cishu))

    dashou_kw = (request_data.get('dashou_keyword') or '').strip()
    if dashou_kw:
        dashou_uids = list(
            User.query.filter(
                Q(UserUID=dashou_kw) |
                Q(UserName__icontains=dashou_kw) |
                Q(Phone__icontains=dashou_kw) |
                Q(DashouProfile__nicheng__icontains=dashou_kw)
            ).values_list('UserUID', flat=True)
        )
        if dashou_uids:
            qs = qs.filter(shenqingren_id__in=dashou_uids)
        else:
            qs = qs.none()

    kg_kw = (request_data.get('kaoheguan_keyword') or '').strip()
    if kg_kw:
        kg_uids = list(
            User.query.filter(
                Q(UserUID=kg_kw) |
                Q(UserName__icontains=kg_kw) |
                Q(Phone__icontains=kg_kw) |
                Q(DashouProfile__nicheng__icontains=kg_kw)
            ).values_list('UserUID', flat=True)
        )
        if kg_uids:
            qs = qs.filter(shenheguan_id__in=kg_uids)
        else:
            qs = qs.none()

    start_time = (request_data.get('start_time') or '').strip()
    end_time = (request_data.get('end_time') or '').strip()
    if start_time:
        qs = qs.filter(CreateTime__gte=start_time)
    if end_time:
        qs = qs.filter(CreateTime__lte=end_time)

    has_kaoheguan = request_data.get('has_kaoheguan')
    if has_kaoheguan in (True, 'true', '1', 1):
        qs = qs.exclude(shenheguan_id__isnull=True).exclude(shenheguan_id='')
    elif has_kaoheguan in (False, 'false', '0', 0):
        qs = qs.filter(Q(shenheguan_id__isnull=True) | Q(shenheguan_id=''))

    return qs


def _serialize_shenhe_jilu_row(jl, profile_map, fee_map=None, reject_count_map=None):
    dashou = profile_map.get(jl.shenqingren_id, {
        'yonghuid': jl.shenqingren_id,
        'avatar': '',
        'phone': '',
        'nicheng': jl.shenqingren_id,
    })
    kaoheguan = None
    if jl.shenheguan_id:
        kaoheguan = profile_map.get(jl.shenheguan_id, {
            'yonghuid': jl.shenheguan_id,
            'avatar': '',
            'phone': '',
            'nicheng': jl.shenheguan_id,
        })
        kaoheguan['game_id'] = jl.shenheguan_youxi_id or ''

    current_fee = 0.0
    if fee_map is not None:
        current_fee = fee_map.get((jl.jilu_id, jl.cishu), 0.0)
    else:
        fd = KaoheJiluFeiyong.query.filter(jilu_id=jl.jilu_id, cishu=jl.cishu).first()
        if fd:
            current_fee = float(fd.jine)

    reject_count = 0
    if reject_count_map is not None:
        reject_count = reject_count_map.get(jl.jilu_id, 0)

    return {
        'jilu_id': jl.jilu_id,
        'zhuangtai': jl.zhuangtai,
        'zhuangtai_text': SHENHE_ZHUANGTAI_MAP.get(jl.zhuangtai, str(jl.zhuangtai)),
        'cishu': jl.cishu,
        'jiaofei_jine': float(jl.jiaofei_jine or 0),
        'current_fee': current_fee,
        'bankuai_id': jl.bankuai.bankuai_id if jl.bankuai else None,
        'bankuai_name': jl.bankuai.mingcheng if jl.bankuai else '',
        'chenghao_id': jl.chenghao.id if jl.chenghao else None,
        'chenghao_name': jl.chenghao.mingcheng if jl.chenghao else '',
        'chenghao_icon': jl.chenghao.tubiao_url if jl.chenghao else '',
        'guize_neirong': jl.guize_neirong or '',
        'dashou': {
            **dashou,
            'game_id': jl.dashou_youxi_id or '',
            'beizhu': jl.dashou_beizhu or '',
        },
        'kaoheguan': kaoheguan,
        'reject_count': reject_count,
        'CreateTime': jl.CreateTime.strftime('%Y-%m-%d %H:%M:%S') if jl.CreateTime else '',
        'UpdateTime': jl.UpdateTime.strftime('%Y-%m-%d %H:%M:%S') if jl.UpdateTime else '',
    }


class KhjlglView(APIView):
    """
    考核记录列表 + 统计
    POST /houtai/khjlgl
    """
    permission_classes = [IsAuthenticated]

    def post(self, request):
        try:
            username_from_frontend = request.data.get('phone', None)
            kefu_obj, permissions = verify_kefu_permission(request, username_from_frontend)
            if kefu_obj is None:
                return permissions
            if 'kaohepeizhi' not in permissions:
                return Response({'code': 403, 'msg': '无考核管理权限'}, status=403)

            page = int(request.data.get('page', 1))
            page_size = int(request.data.get('page_size', 20))
            if page < 1:
                page = 1
            if page_size < 1:
                page_size = 20
            if page_size > 100:
                page_size = 100

            from jituan.services.shenhe_club import filter_shenhe_jilu_by_request

            filter_data = request.data
            qs = filter_shenhe_jilu_by_request(
                _build_shenhe_jilu_filters(filter_data),
                request,
            )

            # FluentQuery.filter() 会原地修改同一对象；统计与列表必须各自独立查询
            stats_base = filter_shenhe_jilu_by_request(
                _build_shenhe_jilu_filters(filter_data),
                request,
            )
            agg = stats_base.aggregate(total_fee=Sum('jiaofei_jine'))
            tag_rows = filter_shenhe_jilu_by_request(
                _build_shenhe_jilu_filters(filter_data),
                request,
            ).values(
                'chenghao_id', 'chenghao__mingcheng'
            ).annotate(
                total=Count('jilu_id'),
                passed=Count('jilu_id', filter=Q(zhuangtai=1)),
                failed=Count('jilu_id', filter=Q(zhuangtai=2)),
                in_progress=Count('jilu_id', filter=Q(zhuangtai=0)),
                pending=Count('jilu_id', filter=Q(zhuangtai=3)),
            ).order_by('-total')

            _stats_agg = stats_base.aggregate(
                total=Count('id'),
                passed=Count('id', filter=Q(zhuangtai=1)),
                failed=Count('id', filter=Q(zhuangtai=2)),
                in_progress=Count('id', filter=Q(zhuangtai=0)),
                pending=Count('id', filter=Q(zhuangtai=3)),
            )
            stats = {
                'total': _stats_agg['total'],
                'passed': _stats_agg['passed'],
                'failed': _stats_agg['failed'],
                'in_progress': _stats_agg['in_progress'],
                'pending': _stats_agg['pending'],
                'total_fee': float(agg['total_fee'] or 0),
                'tag_stats': [
                    {
                        'chenghao_id': r['chenghao_id'],
                        'chenghao_name': r['chenghao__mingcheng'] or '未知标签',
                        'total': r['total'],
                        'passed': r['passed'],
                        'failed': r['failed'],
                        'in_progress': r['in_progress'],
                        'pending': r['pending'],
                    }
                    for r in tag_rows if r['chenghao_id']
                ],
            }

            total = qs.count()
            start = (page - 1) * page_size
            rows = qs.order_by('-CreateTime')[start:start + page_size].to_list()

            uids = []
            jilu_ids = []
            for jl in rows:
                uids.append(jl.shenqingren_id)
                if jl.shenheguan_id:
                    uids.append(jl.shenheguan_id)
                jilu_ids.append(jl.jilu_id)
            profile_map = _batch_user_profile_map(uids)

            fee_pairs = [(jl.jilu_id, jl.cishu) for jl in rows]
            fee_map = {}
            if fee_pairs:
                jids = [p[0] for p in fee_pairs]
                for fd in KaoheJiluFeiyong.query.filter(jilu_id__in=jids):
                    fee_map[(fd.jilu_id, fd.cishu)] = float(fd.jine)

            reject_counts = {
                r['jilu_id']: r['cnt']
                for r in KaoheJujueJilu.query.filter(jilu_id__in=jilu_ids)
                .values('jilu_id')
                .annotate(cnt=Count('id'))
                .all()
            } if jilu_ids else {}

            data_list = [
                _serialize_shenhe_jilu_row(jl, profile_map, fee_map, reject_counts)
                for jl in rows
            ]

            all_bankuai = list(Bankuai.query.values('bankuai_id', 'mingcheng'))
            all_tags = list(
                Chenghao.query.filter(leixing='dashou')
                .values('id', 'mingcheng', 'bankuai_id')
                .order_by('mingcheng')
            )

            return Response({
                'code': 0,
                'msg': 'ok',
                'data': {
                    'total': total,
                    'page': page,
                    'page_size': page_size,
                    'list': data_list,
                    'stats': stats,
                    'all_bankuai': all_bankuai,
                    'all_tags': all_tags,
                },
            })
        except Exception as e:
            logger.exception('KhjlglView 接口错误')
            return Response({'code': 1, 'msg': f'服务器内部错误: {str(e)}'}, status=500)


class KhjlczView(APIView):
    """
    考核记录操作 / 详情
    POST /houtai/khjlcz
    action:
      - get_detail: 获取单条详情（含缴费明细、拒绝历史）
      - to_pending: 考核中 → 待审核（取消指定考核官，与小程序 transfer 一致）
    """
    permission_classes = [IsAuthenticated]

    def post(self, request):
        try:
            username_from_frontend = request.data.get('phone', None)
            kefu_obj, permissions = verify_kefu_permission(request, username_from_frontend)
            if kefu_obj is None:
                return permissions
            if 'kaohepeizhi' not in permissions:
                return Response({'code': 403, 'msg': '无考核管理权限'}, status=403)

            action = request.data.get('action')
            jilu_id = (request.data.get('jilu_id') or '').strip()
            if not jilu_id:
                return Response({'code': 1, 'msg': '缺少记录ID'}, status=400)

            if action == 'get_detail':
                try:
                    jl = ShenheJilu.query.select_related('bankuai', 'chenghao').get(jilu_id=jilu_id)
                except ShenheJilu.DoesNotExist:
                    return Response({'code': 1, 'msg': '记录不存在'}, status=404)

                uids = [jl.shenqingren_id]
                if jl.shenheguan_id:
                    uids.append(jl.shenheguan_id)
                profile_map = _batch_user_profile_map(uids)

                fee_list = [
                    {
                        'cishu': f.cishu,
                        'jine': float(f.jine),
                    }
                    for f in KaoheJiluFeiyong.query.filter(jilu_id=jilu_id).order_by('cishu')
                ]
                reject_list = []
                _reject_records = list(KaoheJujueJilu.query.filter(jilu_id=jilu_id).order_by('-CreateTime'))
                _kg_ids = [r.shenheguan_id for r in _reject_records if r.shenheguan_id]
                _kg_prof_map = _batch_user_profile_map(_kg_ids) if _kg_ids else {}
                for r in _reject_records:
                    kg_prof = _kg_prof_map.get(r.shenheguan_id, {})
                    reject_list.append({
                        'cishu': r.cishu,
                        'shenheguan_id': r.shenheguan_id,
                        'shenheguan_nicheng': kg_prof.get('nicheng', r.shenheguan_id),
                        'yuanyin': r.yuanyin,
                        'CreateTime': r.CreateTime.strftime('%Y-%m-%d %H:%M:%S') if r.CreateTime else '',
                    })

                record = _serialize_shenhe_jilu_row(jl, profile_map)
                record['fee_list'] = fee_list
                record['reject_list'] = reject_list
                return Response({'code': 0, 'msg': 'ok', 'data': record})

            if action == 'to_pending':
                with transaction.atomic():
                    jl = ShenheJilu.objects.select_for_update().filter(jilu_id=jilu_id).first()
                    if not jl:
                        return Response({'code': 1, 'msg': '记录不存在'}, status=404)
                    if jl.zhuangtai != 0:
                        return Response({'code': 1, 'msg': '仅「考核中」的记录可退回待审核'}, status=400)

                    old_kg_id = jl.shenheguan_id
                    jl.shenheguan_id = None
                    jl.shenheguan_youxi_id = None
                    jl.zhuangtai = 3
                    jl.save(update_fields=['shenheguan_id', 'shenheguan_youxi_id', 'zhuangtai', 'UpdateTime'])

                    if old_kg_id:
                        UserShenheguan.query.filter(user__UserUID=old_kg_id).update(shenhe_zhuangtai=0)

                return Response({'code': 0, 'msg': '已退回待审核，考核官指定已取消'})

            return Response({'code': 1, 'msg': '无效的操作类型'}, status=400)

        except Exception as e:
            logger.exception('KhjlczView 接口错误')
            return Response({'code': 1, 'msg': f'服务器内部错误: {str(e)}'}, status=500)

