import io
import os
import re
import time
import random
import secrets
import hashlib
import threading
import urllib.parse
from decimal import Decimal, InvalidOperation

from django.conf import settings
from django.db import transaction, connection
from django.db.models import Q, F, Max, Prefetch
from gvsdsdk.fluent import db, func, FQ
from django.core.cache import cache
from django.core.paginator import Paginator
from django.utils import timezone

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

from utils.oss_utils import upload_to_oss, delete_from_oss, validate_image
from utils.weixin_broadcast import WeixinBroadcastSender
from utils.weixin_token import get_weixin_mini_access_token, is_weixin_token_invalid
# from utils.ip_security import *
from utils.invitationcode_utils import CreateInvitationCode, VerifyInvitationCode

from backend.utils import update_shangjia_daily
from utils.chat_utils import subscribe_merchant_link_chat
from utils.pdd_order_validator import validate_pdd_order_id, validate_cn_mobile

from ..models import (
    Gonggao, Lunbo, Tupianpeizhi, Qunpeizhi,
    ShangjiaMoban, ShangjiaLianjie, PopupPage, PopupConfig, WithdrawConfig,
    MiniappScriptScene, MiniappScriptAutoReply,
)

from users.models import (
    AdminProfile, UserDashou, UserBoss,
    UserShangjia, UserGuanshi, UserZuzhang
)
from users.business_models import User

from orders.models import CommissionRate, Order, MerchantOrderExt
from orders.notice_tasks import dingdan_guangbo

from rank.models import Chenghao, DingdanBiaoqian

from products.models import ShangpinLeixing, Huiyuangoumai

from ..serializers import PopupConfigSerializer
import traceback
import requests

import logging
logger = logging.getLogger(__name__)

class GetDynamicConfigView(APIView):
    permission_classes = [AllowAny]
    parser_classes = [JSONParser]

    def post(self, request):
        try:
            from jituan.services.display_config import get_tupianpeizhi_url

            from jituan.services.miniapp_assets import build_miniapp_assets_payload

            cos_oss_url = getattr(settings, 'COS_DOMAIN', '')
            if cos_oss_url and not cos_oss_url.endswith('/'):
                cos_oss_url += '/'
            cos_bucket = getattr(settings, 'COS_BUCKET', '')
            cos_region = getattr(settings, 'COS_REGION', 'ap-shanghai')
            goeasy_host = 'hangzhou.goeasy.io'
            goeasy_appkey = getattr(settings, 'GOEASY_APPKEY', '')
            kefu_link = getattr(settings, 'KEFU_LINK', '')
            kefu_enterprise_id = getattr(settings, 'KEFU_ENTERPRISE_ID', '')
            rule_img = get_tupianpeizhi_url(request, 1)
            avatar_img = get_tupianpeizhi_url(request, 2)
            morentouxiang = avatar_img or 'beijing/morentouxiang.jpg'
            dashouguize = rule_img or 'a_long/dashouguize.jpg'

            # 构造返回数据
            data = {
                "code": 0,
                "data": {
                    "cos": {
                        "bucket": cos_bucket,
                        "region": cos_region,
                        "ossImageUrl": cos_oss_url,
                        "uploadPathPrefix": "order/"
                    },
                    "goEasy": {
                        "host": goeasy_host,
                        "appkey": goeasy_appkey
                    },
                    "otherConfig": {
                        "morentouxiang": morentouxiang,
                        "dashouguize": dashouguize
                    },
                    "kefu": {
                        "link": kefu_link,
                        "enterpriseId": kefu_enterprise_id
                    },
                    "miniappAssets": build_miniapp_assets_payload(request),
                }
            }
            return Response(data)

        except Exception as e:
            logger.error(f"获取动态配置失败: {str(e)}", exc_info=True)
            return Response({"code": 500, "msg": "服务器内部错误"}, status=500)


class HaibaoPeizhiView(APIView):
    """小程序推广海报背景配置（按俱乐部）。"""
    permission_classes = [AllowAny]
    parser_classes = [JSONParser]

    def post(self, request):
        try:
            from jituan.services.display_config import _display_club_id
            from jituan.services.miniapp_assets import get_poster_payload

            club_id = _display_club_id(request)
            poster = get_poster_payload(club_id)
            return Response({
                'code': 0,
                'msg': 'success',
                'data': {
                    'club_id': club_id,
                    'poster': poster,
                },
            })
        except Exception as e:
            logger.error('获取海报配置失败: %s', e, exc_info=True)
            return Response({'code': 500, 'msg': '服务器内部错误'}, status=500)




class PopupConfigView(APIView):
    """
    获取指定页面的弹窗配置
    请求格式：POST { "pageKey": "dashouzhongxin" }
    返回格式：{ "code": 0, "data": { "serverTime": "...", "popups": [...] } }
    """
    authentication_classes = []
    permission_classes = [AllowAny]

    def post(self, request):
        # 获取参数 pageKey
        page_key = request.data.get('pageKey')
        if not page_key:
            return Response({
                'code': 400,
                'msg': '缺少参数 pageKey'
            }, status=status.HTTP_400_BAD_REQUEST)

        # 3. 查询页面配置（按俱乐部）
        from jituan.services.display_config import get_gonggao_content
        from jituan.services.club_context import resolve_club_id_from_request

        club_id = resolve_club_id_from_request(request)
        try:
            popup_page = PopupPage.query.get(club_id=club_id, page_key=page_key, is_active=True)
        except PopupPage.DoesNotExist:
            # 该页面没有配置弹窗，返回空
            return Response({
                'code': 0,
                'data': {
                    'serverTime': timezone.now().isoformat(),
                    'popups': []
                }
            })

        # 4. 查询该页面下所有启用的弹窗（且在有效时间范围内）
        now = timezone.now()
        popups = PopupConfig.query.filter(
            page=popup_page,
            is_active=True,
            start_time__lte=now,
            end_time__gte=now
        ).prefetch_related('images')  # 预加载图片，避免N+1查询
        # 按 sort_order 排序（model Meta 已定义）

        # 5. 序列化
        serializer = PopupConfigSerializer(popups, many=True)

        # 6. 返回数据
        return Response({
            'code': 0,
            'data': {
                'serverTime': now.isoformat(),
                'ignore_user_mute': popup_page.ignore_user_mute,  # 新增
                'popups': serializer.data
            }
        })




class GetWithdrawModeView(APIView):
    """
    获取提现模式配置
    前端请求 /peizhi/hqtxzsym
    返回格式: { "code": 0, "data": { "mode": 1 or 2 } }
    """
    permission_classes = [IsAuthenticated]  # JWT 认证

    def post(self, request, *args, **kwargs):
        from jituan.services.club_context import resolve_club_id_from_request
        from jituan.services.club_user import get_user_club_id
        from jituan.services.withdraw_config import get_withdraw_mode

        user = getattr(request, 'user', None)
        club_id = get_user_club_id(user) if user and getattr(user, 'is_authenticated', False) else None
        if not club_id:
            club_id = resolve_club_id_from_request(request)
        mode = get_withdraw_mode(club_id)

        return Response({
            'code': 0,
            'data': {
                'mode': mode,
                'club_id': club_id,
            }
        })





class CheckPhoneAuthView(APIView):
    """
    判断当前登录用户是否需要强制手机号认证

    规则：
      - 已认证过手机号（PhoneVerified=True） → 不需要
      - 未认证时，满足以下任一条件 → 需要认证：
        打手：有会员购买记录，或押金 > 0
        商家：已是商家（存在商家扩展表）
        管事：已是管事（存在管事扩展表）
        组长：已是组长（存在组长扩展表）
        老板：有下单记录（alldingdan > 0）
        子客服：已是有效商家客服（merchant_staff_member 活跃）
    """

    permission_classes = [IsAuthenticated]

    @staticmethod
    def _phone_auth_completed(user):
        """是否已完成手机号认证（兼容 PhoneVerified 未写入的老数据）。"""
        if bool(getattr(user, 'PhoneVerified', False)):
            return True
        phone = (getattr(user, 'Phone', None) or '').strip()
        return len(phone) >= 11

    def post(self, request):
        uid = getattr(request.user, 'UserUID', None)
        user = request.user
        if uid:
            try:
                user = User.query.get(UserUID=uid)
            except User.DoesNotExist:
                user = request.user

        # 俱乐部关闭强制收集手机号 → 前端 ensurePhoneAuth 不再跳转认证页
        try:
            from jituan.services.club_context import resolve_effective_club_id
            from jituan.services.force_phone_auth import is_club_force_phone_auth
            club_id = resolve_effective_club_id(request, user)
            if not is_club_force_phone_auth(club_id):
                return Response({'code': 0, 'need_auth': False})
        except Exception:
            pass

        if self._phone_auth_completed(user):
            return Response({'code': 0, 'need_auth': False})

        if self._dashou_meets_threshold(user):
            return Response({'code': 0, 'need_auth': True})
        if self._shangjia_meets_threshold(user):
            return Response({'code': 0, 'need_auth': True})
        if self._guanshi_meets_threshold(user):
            return Response({'code': 0, 'need_auth': True})
        if self._zuzhang_meets_threshold(user):
            return Response({'code': 0, 'need_auth': True})
        if self._boss_meets_threshold(user):
            return Response({'code': 0, 'need_auth': True})
        if self._staff_meets_threshold(user):
            return Response({'code': 0, 'need_auth': True})

        return Response({'code': 0, 'need_auth': False})

    def _staff_meets_threshold(self, user):
        """子客服：已是有效商家客服"""
        try:
            from merchant_ops.services.authz import get_active_staff_member
            return get_active_staff_member(user) is not None
        except Exception:
            return False

    def _dashou_meets_threshold(self, user):
        """打手：有会员记录、押金 > 0、或有过接单/成交订单"""
        try:
            dashou = UserDashou.query.get(user=user)
        except UserDashou.DoesNotExist:
            return False
        if dashou.yajin and dashou.yajin > 0:
            return True
        from jituan.services.club_context import resolve_effective_club_id
        club_id = resolve_effective_club_id(self.request, user)
        if Huiyuangoumai.query.filter(yonghu_id=user.UserUID, club_id=club_id).exists():
            return True
        if (dashou.jiedanzongliang or 0) > 0 or (dashou.chengjiaozongliang or 0) > 0:
            return True
        return Order.query.filter(PlayerID=user.UserUID).exists()

    def _shangjia_meets_threshold(self, user):
        """商家：已是商家身份"""
        return UserShangjia.query.filter(user=user).exists()

    def _guanshi_meets_threshold(self, user):
        """管事：已是管事身份"""
        return UserGuanshi.query.filter(user=user).exists()

    def _zuzhang_meets_threshold(self, user):
        """组长：已是组长身份"""
        return UserZuzhang.query.filter(user=user).exists()

    def _boss_meets_threshold(self, user):
        """老板：有下单记录"""
        try:
            boss = UserBoss.query.get(user=user)
        except UserBoss.DoesNotExist:
            return False
        return (boss.alldingdan or 0) > 0


