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']

class GetMemberListView(APIView):
    """
    获取会员列表
    权限：3300a
    POST /houtai/hthqhylb
    参数：username
    返回：code:0, data: { list: [...] }
    """
    permission_classes = []
    parser_classes = [JSONParser]

    def post(self, request):
        username = request.data.get('username', '').strip()
        if not username:
            return Response({'code': 401, 'msg': '缺少username'})

        kefu, permissions = verify_kefu_permission(request, username)
        if kefu is None:
            return permissions
        if '3300a' not in permissions:
            return Response({'code': 403, 'msg': '无权限查看会员列表'})

        from jituan.services.club_member_admin import build_member_list_payload

        payload = build_member_list_payload(request)
        return Response({
            'code': 0,
            'data': {'list': payload['list']},
            'club_id': payload.get('club_id'),
            'scope': payload.get('scope'),
            'price_note': payload.get('price_note'),
        })


class UpdateMemberView(APIView):
    """
    修改会员信息
    权限：3300a
    POST /houtai/htxghyxx
    参数：
        username, huiyuan_id, jieshao, jiage, guanshifc, zuzhangfc, jtjieshao
    返回：code:0 成功
    """
    permission_classes = []
    parser_classes = [JSONParser]

    def post(self, request):
        username = request.data.get('username', '').strip()
        huiyuan_id = request.data.get('huiyuan_id', '').strip()
        jieshao = request.data.get('jieshao', '').strip()
        jiage = request.data.get('jiage')
        guanshifc = request.data.get('guanshifc')
        zuzhangfc = request.data.get('zuzhangfc')
        jtjieshao = request.data.get('jtjieshao', '').strip()

        if not username:
            return Response({'code': 401, 'msg': '缺少username'})
        if not huiyuan_id:
            return Response({'code': 400, 'msg': '缺少会员ID'})
        if not jieshao:
            return Response({'code': 400, 'msg': '会员名称不能为空'})

        try:
            jiage = Decimal(str(jiage))
            guanshifc = Decimal(str(guanshifc))
            zuzhangfc = Decimal(str(zuzhangfc))
            if jiage < 0 or guanshifc < 0 or zuzhangfc < 0:
                raise ValueError
        except:
            return Response({'code': 400, 'msg': '金额格式错误'})

        if guanshifc + zuzhangfc > jiage:
            return Response({'code': 400, 'msg': '管事分成+组长分成不能大于会员价格'})

        # 权限校验
        kefu, permissions = verify_kefu_permission(request, username)
        if kefu is None:
            return permissions
        if '3300a' not in permissions:
            return Response({'code': 403, 'msg': '无权限修改会员'})

        from jituan.services.club_member_admin import update_member_for_club

        extra = {
            'formal_days': request.data.get('formal_days'),
            'trial_enabled': request.data.get('trial_enabled'),
            'trial_price': request.data.get('trial_price'),
            'trial_days': request.data.get('trial_days'),
            'trial_guanshifc': request.data.get('trial_guanshifc'),
            'trial_zuzhangfc': request.data.get('trial_zuzhangfc'),
            'card_image': request.data.get('card_image'),
            'card_bg': request.data.get('card_bg'),
            'included_huiyuan_ids': request.data.get('included_huiyuan_ids'),
        }
        data, err = update_member_for_club(
            request, huiyuan_id, jieshao, jiage, guanshifc, zuzhangfc, jtjieshao, extra=extra,
        )
        if err:
            return Response({'code': 400, 'msg': err})
        return Response({'code': 0, 'msg': '修改成功'})



class AddMemberView(APIView):
    """
    添加会员
    权限：3300a
    POST /houtai/httjhy
    参数：
        username, jieshao, jiage, guanshifc, zuzhangfc, jtjieshao
    返回：code:0, data: { huiyuan_id }
    """
    permission_classes = []
    parser_classes = [JSONParser]

    def post(self, request):
        username = request.data.get('username', '').strip()
        jieshao = request.data.get('jieshao', '').strip()
        jiage = request.data.get('jiage')
        guanshifc = request.data.get('guanshifc')
        zuzhangfc = request.data.get('zuzhangfc')
        jtjieshao = request.data.get('jtjieshao', '').strip()

        if not username:
            return Response({'code': 401, 'msg': '缺少username'})
        if not jieshao:
            return Response({'code': 400, 'msg': '会员名称不能为空'})

        try:
            jiage = Decimal(str(jiage))
            guanshifc = Decimal(str(guanshifc))
            zuzhangfc = Decimal(str(zuzhangfc))
            if jiage <= 0 or guanshifc < 0 or zuzhangfc < 0:
                raise ValueError
        except:
            return Response({'code': 400, 'msg': '金额格式错误'})

        if guanshifc + zuzhangfc > jiage:
            return Response({'code': 400, 'msg': '管事分成+组长分成不能大于会员价格'})

        # 权限校验
        kefu, permissions = verify_kefu_permission(request, username)
        if kefu is None:
            return permissions
        if '3300a' not in permissions:
            return Response({'code': 403, 'msg': '无权限添加会员'})

        from jituan.services.club_member_admin import add_global_member
        from jituan.services.club_context import resolve_club_scope
        from jituan.constants import DATA_SCOPE_ALL

        if resolve_club_scope(request) != DATA_SCOPE_ALL and '000001' not in permissions:
            return Response({
                'code': 403,
                'msg': '仅集团汇总视图可新建全局会员类型；俱乐部请从会员 catalog 上架',
            })

        data, err = add_global_member(
            jieshao, jiage, guanshifc, zuzhangfc, jtjieshao,
            is_bundle=bool(request.data.get('is_bundle')),
        )
        if err:
            return Response({'code': 400, 'msg': err})
        return Response({'code': 0, 'msg': '添加成功', 'data': data})




class ClubMemberCatalogView(APIView):
    """俱乐部可上架的集团会员 catalog。POST /houtai/hthycatalog"""
    permission_classes = []
    parser_classes = [JSONParser]

    def post(self, request):
        username = request.data.get('username', '').strip()
        if not username:
            return Response({'code': 401, 'msg': '缺少username'})
        kefu, permissions = verify_kefu_permission(request, username)
        if kefu is None:
            return permissions
        if '3300a' not in permissions:
            return Response({'code': 403, 'msg': '无权限'})
        from jituan.services.club_member_admin import build_member_catalog_payload
        return Response({'code': 0, 'data': build_member_catalog_payload(request)})


class ClubMemberEnableView(APIView):
    """俱乐部上架会员。POST /houtai/hthysj"""
    permission_classes = []
    parser_classes = [JSONParser]

    def post(self, request):
        username = request.data.get('username', '').strip()
        huiyuan_id = request.data.get('huiyuan_id', '').strip()
        if not username or not huiyuan_id:
            return Response({'code': 400, 'msg': '参数不完整'})
        kefu, permissions = verify_kefu_permission(request, username)
        if kefu is None:
            return permissions
        if '3300a' not in permissions:
            return Response({'code': 403, 'msg': '无权限'})
        try:
            jiage = Decimal(str(request.data.get('jiage')))
            guanshifc = Decimal(str(request.data.get('guanshifc')))
            zuzhangfc = Decimal(str(request.data.get('zuzhangfc')))
        except Exception:
            return Response({'code': 400, 'msg': '金额格式错误'})
        from jituan.services.club_member_admin import enable_member_for_club
        extra = request.data
        data, err = enable_member_for_club(
            request, huiyuan_id, jiage, guanshifc, zuzhangfc, extra=extra,
        )
        if err:
            return Response({'code': 400, 'msg': err})
        return Response({'code': 0, 'msg': '上架成功', 'data': data})


class ClubMemberDisableView(APIView):
    """俱乐部下架会员。POST /houtai/hthyxj"""
    permission_classes = []
    parser_classes = [JSONParser]

    def post(self, request):
        username = request.data.get('username', '').strip()
        huiyuan_id = request.data.get('huiyuan_id', '').strip()
        if not username or not huiyuan_id:
            return Response({'code': 400, 'msg': '参数不完整'})
        kefu, permissions = verify_kefu_permission(request, username)
        if kefu is None:
            return permissions
        if '3300a' not in permissions:
            return Response({'code': 403, 'msg': '无权限'})
        from jituan.services.club_member_admin import disable_member_for_club
        data, err = disable_member_for_club(request, huiyuan_id)
        if err:
            return Response({'code': 400, 'msg': err})
        return Response({'code': 0, 'msg': '已下架', 'data': data})


class MemberCardImageUploadView(APIView):
    """POST /jituan/houtai/hy-card-upload 上传会员充值卡片图"""
    permission_classes = []
    parser_classes = [MultiPartParser, FormParser, JSONParser]

    def post(self, request):
        username = (request.data.get('username') or request.data.get('phone') or '').strip()
        huiyuan_id = (request.data.get('huiyuan_id') or '').strip()
        field = (request.data.get('field') or 'card_image').strip()
        file_obj = request.FILES.get('file')
        if not username or not huiyuan_id or not file_obj:
            return Response({'code': 400, 'msg': '参数不完整'})
        kefu, permissions = verify_kefu_permission(request, username)
        if kefu is None:
            return permissions
        if '3300a' not in permissions:
            return Response({'code': 403, 'msg': '无权限'})
        from jituan.services.club_member_admin import upload_member_card_image
        data, err = upload_member_card_image(request, huiyuan_id, field, file_obj)
        if err:
            return Response({'code': 400, 'msg': err})
        return Response({'code': 0, 'msg': '上传成功', 'data': data})


class MemberRechargeRecordsView(APIView):
    """POST /jituan/houtai/hy-recharge-records — 会员充值记录明细 + 分红"""
    permission_classes = []
    parser_classes = [JSONParser]

    def post(self, request):
        username = (request.data.get('username') or request.data.get('phone') or '').strip()
        if not username:
            return Response({'code': 401, 'msg': '缺少username'})
        kefu, permissions = verify_kefu_permission(request, username)
        if kefu is None:
            return permissions
        if '3300a' not in permissions:
            return Response({'code': 403, 'msg': '无权限查看会员充值记录'})

        from jituan.services.member_recharge_records import build_member_recharge_records_payload

        filters = request.data.get('filters') or {}
        for key in (
            'dingdan_id', 'yonghuid', 'buyer_keyword', 'huiyuan_id', 'is_trial',
            'zhuangtai', 'date_from', 'date_to', 'jine_min', 'jine_max',
            'guanshi_id', 'zuzhang_id', 'keyword', 'is_bundle', 'has_fenhong', 'club_id',
        ):
            if request.data.get(key) not in (None, ''):
                filters[key] = request.data.get(key)

        payload = build_member_recharge_records_payload(
            request,
            filters=filters,
            page=request.data.get('page', 1),
            page_size=request.data.get('page_size', 20),
        )
        return Response({'code': 0, 'data': payload})


class MemberBundleCreateView(APIView):
    """POST /jituan/houtai/hy-bundle-create — 俱乐部一键创建总会员并上架"""
    permission_classes = []
    parser_classes = [JSONParser]

    def post(self, request):
        username = (request.data.get('username') or request.data.get('phone') or '').strip()
        if not username:
            return Response({'code': 401, 'msg': '缺少username'})
        kefu, permissions = verify_kefu_permission(request, username)
        if kefu is None:
            return permissions
        if '3300a' not in permissions:
            return Response({'code': 403, 'msg': '无权限'})

        jieshao = (request.data.get('jieshao') or '').strip()
        if not jieshao:
            return Response({'code': 400, 'msg': '会员名称不能为空'})

        try:
            jiage = Decimal(str(request.data.get('jiage')))
            guanshifc = Decimal(str(request.data.get('guanshifc')))
            zuzhangfc = Decimal(str(request.data.get('zuzhangfc')))
        except Exception:
            return Response({'code': 400, 'msg': '金额格式错误'})

        from jituan.services.club_member_admin import create_bundle_member_for_club

        data, err = create_bundle_member_for_club(
            request,
            jieshao=jieshao,
            jiage=jiage,
            guanshifc=guanshifc,
            zuzhangfc=zuzhangfc,
            jtjieshao=(request.data.get('jtjieshao') or '').strip(),
            formal_days=int(request.data.get('formal_days') or 30),
            included_huiyuan_ids=request.data.get('included_huiyuan_ids') or [],
        )
        if err:
            return Response({'code': 400, 'msg': err})
        return Response({'code': 0, 'msg': '总会员创建并上架成功', 'data': data})


