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__)

# 小程序客服话术 / 自动回复默认值（原位于 miniapp_config.py，按功能组归类到话术模块）
MINIAPP_SCRIPT_DEFAULTS = {
    'cs_welcome': {
        'title': '',
        'content': '你好，请问有什么可以帮到您的？',
        'confirm_text': '',
        'cancel_text': '',
    },
    'chat_image_confirm': {
        'title': '温馨提示',
        'content': '平台禁止任何违法违规行为，聊天内容仅限于商家与接单员正常业务对接。严禁赌博、诈骗及其他非法行为，违者后果自负。',
        'confirm_text': '确认',
        'cancel_text': '取消',
    },
    'merchant_dispatch_confirm': {
        'title': '确认派单',
        'content': '确认向该打手派发此订单？',
        'confirm_text': '确认',
        'cancel_text': '取消',
    },
}

def _resolve_script_club_id(request):
    from jituan.services.club_context import resolve_club_id_from_request
    from jituan.services.club_user import get_user_club_id
    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)
    return club_id or 'xq'


def _merge_script_scene(scene_key, row):
    base = dict(MINIAPP_SCRIPT_DEFAULTS.get(scene_key) or {})
    if not row:
        return base
    if row.title:
        base['title'] = row.title
    if row.content:
        base['content'] = row.content
    if row.confirm_text:
        base['confirm_text'] = row.confirm_text
    if row.cancel_text:
        base['cancel_text'] = row.cancel_text
    return base


class HuashuHqView(APIView):
    """POST /peizhi/huashuhq  批量获取场景话术"""
    permission_classes = [IsAuthenticated]

    def post(self, request):
        scene_keys = request.data.get('scene_keys') or []
        if not isinstance(scene_keys, list) or not scene_keys:
            return Response({'code': 400, 'msg': 'scene_keys 不能为空', 'data': None}, status=400)
        club_id = _resolve_script_club_id(request)
        rows = MiniappScriptScene.query.filter(
            club_id=club_id, scene_key__in=scene_keys, enabled=True,
        )
        row_map = {r.scene_key: r for r in rows}
        data = {}
        for key in scene_keys:
            if not isinstance(key, str) or not key.strip():
                continue
            data[key.strip()] = _merge_script_scene(key.strip(), row_map.get(key.strip()))
        return Response({'code': 200, 'msg': 'success', 'data': data})


class HuashuMatchView(APIView):
    """POST /peizhi/huashu_match  客服关键词自动回复匹配"""
    permission_classes = [IsAuthenticated]

    def post(self, request):
        scene_key = (request.data.get('scene_key') or '').strip()
        user_text = (request.data.get('user_text') or '').strip()
        if scene_key != 'cs_auto_reply':
            return Response({'code': 400, 'msg': '不支持的 scene_key', 'data': {'matched': False, 'content': ''}})
        if not user_text:
            return Response({'code': 200, 'msg': 'success', 'data': {'matched': False, 'content': ''}})
        club_id = _resolve_script_club_id(request)
        rules = MiniappScriptAutoReply.query.filter(
            club_id=club_id, enabled=True,
        ).order_by('-sort_order', 'id')
        text_lower = user_text.lower()
        for rule in rules:
            kw_raw = (rule.keyword or '').strip()
            if not kw_raw:
                continue
            keywords = [k.strip() for k in kw_raw.split(',') if k.strip()]
            for kw in keywords:
                if kw.lower() in text_lower or kw in user_text:
                    reply_type = rule.reply_type or MiniappScriptAutoReply.REPLY_TEXT
                    return Response({
                        'code': 200,
                        'msg': 'success',
                        'data': {
                            'matched': True,
                            'content': rule.reply_content or '',
                            'reply_type': reply_type,
                        },
                    })
        return Response({'code': 200, 'msg': 'success', 'data': {'matched': False, 'content': ''}})


# ---------- 后台：客服话术配置（/houtai/hthqhs、/houtai/htxghs） ----------

SCRIPT_CONFIG_PERMS = ('kfhs666', '8080a')
SCRIPT_SCENE_KEYS = ('chat_image_confirm', 'cs_welcome', 'merchant_dispatch_confirm')


def _has_script_config_perm(permissions):
    return any(code in permissions for code in SCRIPT_CONFIG_PERMS)


def _script_scene_item_type(scene_key):
    return 'text_display' if scene_key == 'cs_welcome' else 'confirm_modal'


def _serialize_script_scene(row):
    return {
        'id': row.id,
        'scene_key': row.scene_key,
        'item_type': _script_scene_item_type(row.scene_key),
        'title': row.title or '',
        'content': row.content or '',
        'confirm_text': row.confirm_text or '',
        'cancel_text': row.cancel_text or '',
        'is_active': bool(row.enabled),
    }


def _serialize_script_auto_reply(row):
    keywords = [k.strip() for k in (row.keyword or '').split(',') if k.strip()]
    return {
        'id': row.id,
        'scene_key': 'cs_auto_reply',
        'item_type': 'auto_reply',
        'title': '',
        'keywords': keywords,
        'match_mode': 'contains',
        'priority': row.sort_order or 0,
        'content': row.reply_content or '',
        'is_active': bool(row.enabled),
    }


class MiniappScriptHoutaiListView(APIView):
    """POST /houtai/hthqhs  后台获取话术与自动回复配置"""
    permission_classes = [IsAuthenticated]

    def post(self, request):
        from backend.utils import verify_kefu_permission

        username = request.data.get('username')
        kefu, permissions = verify_kefu_permission(request, username)
        if kefu is None:
            return Response({'code': 403, 'msg': '身份验证失败，请检查登录状态'})
        if not _has_script_config_perm(permissions):
            return Response({'code': 403, 'msg': '您没有权限访问客服聊天配置'})

        club_id = _resolve_script_club_id(request)
        scenes = MiniappScriptScene.query.filter(
            club_id=club_id, scene_key__in=SCRIPT_SCENE_KEYS,
        ).order_by('scene_key')
        auto_rules = MiniappScriptAutoReply.query.filter(club_id=club_id).order_by('-sort_order', 'id')

        items = [_serialize_script_scene(r) for r in scenes]
        items.extend(_serialize_script_auto_reply(r) for r in auto_rules)
        return Response({'code': 0, 'data': {'items': items, 'club_id': club_id}})


class MiniappScriptHoutaiModifyView(APIView):
    """POST /houtai/htxghs  后台增删改话术与自动回复"""
    permission_classes = [IsAuthenticated]

    def post(self, request):
        from backend.utils import verify_kefu_permission
        from jituan.services.display_config import forbid_display_write_in_all_scope

        username = request.data.get('username')
        kefu, permissions = verify_kefu_permission(request, username)
        if kefu is None:
            return Response({'code': 403, 'msg': '身份验证失败，请检查登录状态'})
        if not _has_script_config_perm(permissions):
            return Response({'code': 403, 'msg': '您没有权限操作客服聊天配置'})

        action = (request.data.get('action') or '').strip()
        if not action:
            return Response({'code': 400, 'msg': '缺少 action 参数'})

        club_id = _resolve_script_club_id(request)

        if action == 'delete':
            return self._delete_item(request, club_id)

        deny = forbid_display_write_in_all_scope(request)
        if deny:
            return deny

        if action in ('create', 'update'):
            item_type = (request.data.get('item_type') or '').strip()
            if item_type == 'auto_reply':
                return self._save_auto_reply(request, club_id, action)
            return self._save_scene(request, club_id, action)

        return Response({'code': 400, 'msg': f'未知的 action: {action}'})

    def _save_scene(self, request, club_id, action):
        scene_key = (request.data.get('scene_key') or '').strip()
        if scene_key not in SCRIPT_SCENE_KEYS:
            return Response({'code': 400, 'msg': '不支持的 scene_key'})

        content = (request.data.get('content') or '').strip()
        if not content:
            return Response({'code': 400, 'msg': '请填写正文内容'})

        fields = {
            'title': (request.data.get('title') or '').strip(),
            'content': content,
            'confirm_text': (request.data.get('confirm_text') or '').strip(),
            'cancel_text': (request.data.get('cancel_text') or '').strip(),
            'enabled': bool(request.data.get('is_active', True)),
        }

        if action == 'update':
            row_id = request.data.get('id')
            if not row_id:
                return Response({'code': 400, 'msg': '缺少 id'})
            row = MiniappScriptScene.query.filter(id=row_id, club_id=club_id).first()
            if not row:
                return Response({'code': 404, 'msg': '配置不存在'})
            for k, v in fields.items():
                setattr(row, k, v)
            row.save()
            return Response({'code': 0, 'msg': '保存成功', 'data': _serialize_script_scene(row)})

        existing = MiniappScriptScene.query.filter(club_id=club_id, scene_key=scene_key).first()
        if existing:
            for k, v in fields.items():
                setattr(existing, k, v)
            existing.save()
            return Response({'code': 0, 'msg': '保存成功', 'data': _serialize_script_scene(existing)})

        row = MiniappScriptScene.query.create(club_id=club_id, scene_key=scene_key, **fields)
        return Response({'code': 0, 'msg': '创建成功', 'data': _serialize_script_scene(row)})

    def _save_auto_reply(self, request, club_id, action):
        keywords = request.data.get('keywords') or []
        if not isinstance(keywords, list) or not keywords:
            return Response({'code': 400, 'msg': '请至少添加一个触发关键词'})

        kw_list = [str(k).strip() for k in keywords if str(k).strip()]
        if not kw_list:
            return Response({'code': 400, 'msg': '请至少添加一个触发关键词'})

        content = (request.data.get('content') or '').strip()
        if not content:
            return Response({'code': 400, 'msg': '请填写回复内容'})

        fields = {
            'keyword': ','.join(kw_list),
            'reply_content': content,
            'sort_order': int(request.data.get('priority') or 0),
            'enabled': bool(request.data.get('is_active', True)),
            'reply_type': MiniappScriptAutoReply.REPLY_TEXT,
        }

        if action == 'update':
            row_id = request.data.get('id')
            if not row_id:
                return Response({'code': 400, 'msg': '缺少 id'})
            row = MiniappScriptAutoReply.query.filter(id=row_id, club_id=club_id).first()
            if not row:
                return Response({'code': 404, 'msg': '规则不存在'})
            for k, v in fields.items():
                setattr(row, k, v)
            row.save()
            return Response({'code': 0, 'msg': '保存成功', 'data': _serialize_script_auto_reply(row)})

        row = MiniappScriptAutoReply.query.create(club_id=club_id, **fields)
        return Response({'code': 0, 'msg': '创建成功', 'data': _serialize_script_auto_reply(row)})

    def _delete_item(self, request, club_id):
        from jituan.services.display_config import forbid_display_write_in_all_scope

        deny = forbid_display_write_in_all_scope(request)
        if deny:
            return deny

        row_id = request.data.get('id')
        if not row_id:
            return Response({'code': 400, 'msg': '缺少 id'})

        row = MiniappScriptAutoReply.query.filter(id=row_id, club_id=club_id).first()
        if row:
            row.delete()
            return Response({'code': 0, 'msg': '删除成功'})

        row = MiniappScriptScene.query.filter(id=row_id, club_id=club_id).first()
        if row:
            return Response({'code': 400, 'msg': '场景话术不支持删除，请改为禁用'})

        return Response({'code': 404, 'msg': '记录不存在'})
