"""shop.views.shop_product_views - 商品类型专区与商品数据管理视图."""
# ==================== 标准库 ====================
import io
import json
import time
import random
import string
import hmac
import hashlib
import requests
import logging
import traceback
import calendar
import threading
import xmltodict
from decimal import Decimal
from collections import defaultdict
from concurrent.futures import ThreadPoolExecutor, as_completed

from django.conf import settings
from django.db import models, transaction, IntegrityError
from django.db.models import F, Sum, Count, Q, Prefetch
from gvsdsdk.fluent import db, func, FQ
from django.core.cache import cache
from django.core.paginator import Paginator, EmptyPage
from django.core.exceptions import ObjectDoesNotExist
from django.utils import timezone
from django.http import HttpResponse

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework_simplejwt.tokens import RefreshToken

from utils.oss_utils import upload_to_oss, delete_from_oss, get_oss_client
from utils.money import yuan_to_fen

from ..utils import verify_shop_permission
from shop.utils import verify_shop_permission, update_dianpu_daily_stat
from products.utils import update_shangpin_daily_stat
from orders.utils import update_daily_payout
from backend.utils import update_dashou_daily_by_action

from ..models import YonghuPingzheng, Dianpu, DianpuShouzhiMeiriTongji

from users.models import UserDashou, UserShangjia, UserGuanshi, UserZuzhang
from users.business_models import User

from shop.models import YonghuDianpuBangding, ShangpinLeixingDianpu, DianpuShangpinShenheShezhi

from products.models import ShangpinLeixing, ShangpinZhuanqu, Shangpin, Huiyuan

from orders.models import (
    Order, PlatformOrderExt, PlayerDeliveryImage, RefundRecord,
    OrderPlayerHistory, Penalty
)


logger = logging.getLogger(__name__)

class ShopProductConfigView(APIView):
    """
    获取商品发布所需配置：公共类型、店铺商品类型、专区及各自商品数量
    URL: /shangdian/dphqspxx
    权限: JWT认证 + 店铺归属验证
    """
    permission_classes = [IsAuthenticated]

    def post(self, request):
        # 1. 身份验证，获取店铺对象
        frontend_user_id = request.data.get('userId')
        if not frontend_user_id:
            return Response({'code': 400, 'msg': '缺少必要参数 userId'})

        dianpu, error = verify_shop_permission(request, frontend_user_id)
        if error:
            return error

        # ---------- 2. 公共商品类型（需审核正常） ----------
        try:
            public_types_qs = ShangpinLeixing.query.filter(shenhezhuangtai=1).values(
                'id', 'jieshao', 'tupian_url'
            )
            public_types = [{
                'id': pt['id'],
                'jieshao': pt['jieshao'] or '',
                'tupian_url': pt['tupian_url'] or '',
            } for pt in public_types_qs]
        except Exception as e:
            logger.exception("查询公共商品类型失败")
            return Response({'code': 500, 'msg': '服务器错误'})

        # ---------- 3. 店铺商品类型 ----------
        try:
            shop_types = ShangpinLeixingDianpu.query.filter(
                dianpu_id=dianpu.id
            ).select_related('gonggong_leixing').order_by('-paixu')
        except Exception as e:
            logger.exception("查询店铺商品类型失败")
            return Response({'code': 500, 'msg': '服务器错误'})

        type_ids = []
        shop_product_types = []
        for t in shop_types:
            shop_product_types.append({
                'id': t.id,
                'jieshao': t.jieshao or '',
                'tupian_url': t.tupian_url or '',
                'paixu': t.paixu,
                'shangjia_zhuangtai': t.shangjia_zhuangtai,
                'fengjin_zhuangtai': t.fengjin_zhuangtai,
                'shenhe_zhuangtai': t.shenhe_zhuangtai,
                'gonggong_leixing_id': t.gonggong_leixing_id,
            })
            type_ids.append(t.id)

        # ---------- 4. 各类型商品数量统计 ----------
        type_product_counts = {}
        if type_ids:
            counts = Shangpin.query.filter(
                dianpu_id=dianpu.id,
                dianpu_leixing_id__in=type_ids
            ).values('dianpu_leixing_id').annotate(cnt=Count('id'))
            type_product_counts = {item['dianpu_leixing_id']: item['cnt'] for item in counts}

        # ---------- 5. 专区列表 ----------
        try:
            zhuanqu_qs = ShangpinZhuanqu.query.filter(
                dianpu_id=dianpu.id
            ).order_by('-paixu').values(
                'id', 'mingzi', 'paixu', 'shangjia_zhuangtai',
                'fengjin_zhuangtai', 'dianpu_leixing_id'
            )
            zhuanqu_list = []
            zhuanqu_ids = []
            for zq in zhuanqu_qs:
                zhuanqu_list.append({
                    'id': zq['id'],
                    'mingzi': zq['mingzi'] or '',
                    'paixu': zq['paixu'],
                    'shangjia_zhuangtai': zq['shangjia_zhuangtai'],
                    'fengjin_zhuangtai': zq['fengjin_zhuangtai'],
                    'dianpu_leixing_id': zq['dianpu_leixing_id'],
                })
                zhuanqu_ids.append(zq['id'])
        except Exception as e:
            logger.exception("查询专区失败")
            return Response({'code': 500, 'msg': '服务器错误'})

        # ---------- 6. 各专区商品数量统计 ----------
        zhuanqu_product_counts = {}
        if zhuanqu_ids:
            counts = Shangpin.query.filter(
                dianpu_id=dianpu.id,
                zhuanqu_id__in=zhuanqu_ids
            ).values('zhuanqu_id').annotate(cnt=Count('id'))
            zhuanqu_product_counts = {item['zhuanqu_id']: item['cnt'] for item in counts}

        return Response({
            'code': 0,
            'msg': 'success',
            'data': {
                'public_types': public_types,
                'shop_product_types': shop_product_types,
                'zhuanqu_list': zhuanqu_list,
                'type_product_counts': type_product_counts,
                'zhuanqu_product_counts': zhuanqu_product_counts,
            }
        })




class ShopProductModifyView(APIView):
    """店铺商品类型与专区管理（增、改、删）"""
    permission_classes = [IsAuthenticated]

    def post(self, request):
        try:
            frontend_user_id = request.data.get('userId') or request.POST.get('userId')
            if not frontend_user_id:
                return Response({'code': 400, 'msg': '缺少必要参数 userId'})

            dianpu, error = verify_shop_permission(request, frontend_user_id)
            if error:
                return error

            action = request.data.get('action') or request.POST.get('action')
            if not action:
                return Response({'code': 400, 'msg': '缺少操作类型 action'})

            handlers = {
                'add_type': self._add_type,
                'update_type': self._update_type,
                'delete_type': self._delete_type,
                'add_zhuanqu': self._add_zhuanqu,
                'update_zhuanqu': self._update_zhuanqu,
                'delete_zhuanqu': self._delete_zhuanqu,
            }
            handler = handlers.get(action)
            if not handler:
                return Response({'code': 400, 'msg': '不支持的操作类型'})

            return handler(dianpu, request)

        except Exception as e:
            logger.exception("ShopProductModifyView 全局异常")
            return Response({'code': 500, 'msg': '服务器内部错误'})

    # ---------- 商品类型操作 ----------
    @transaction.atomic
    def _add_type(self, dianpu, request):
        """添加店铺商品类型"""
        try:
            jieshao = request.data.get('jieshao') or request.POST.get('jieshao')
            gonggong_leixing_id = request.data.get('gonggong_leixing_id') or request.POST.get('gonggong_leixing_id')
            paixu = request.data.get('paixu', 0) or request.POST.get('paixu', 0)

            if not jieshao or not gonggong_leixing_id:
                return Response({'code': 400, 'msg': '缺少介绍或公共类型ID'})

            # 验证公共类型存在且正常
            if not ShangpinLeixing.query.filter(id=gonggong_leixing_id, shenhezhuangtai=1).exists():
                return Response({'code': 400, 'msg': '所选公共商品类型无效'})

            image_file = request.FILES.get('image')
            if not image_file:
                return Response({'code': 400, 'msg': '必须上传类型图片'})

            # 上传图片
            file_path = f"dianpu/shangpin/shangpinleixing/{dianpu.id}_{int(time.time())}.png"
            full_url = upload_to_oss(image_file, file_path)
            if not full_url:
                return Response({'code': 500, 'msg': '图片上传失败'})

            # 提取相对路径
            tupian_url = full_url.replace(settings.COS_DOMAIN.rstrip('/') + '/', '', 1)

            # 审核状态（按店铺所属俱乐部）
            from shop.services.shenhe_config import is_kaiqi_shenhe_enabled
            shop_club = getattr(dianpu, 'club_id', None) or 'xq'
            shenhe_status = not is_kaiqi_shenhe_enabled(shop_club)

            ShangpinLeixingDianpu.query.create(
                dianpu_id=dianpu.id,
                gonggong_leixing_id=gonggong_leixing_id,
                jieshao=jieshao,
                tupian_url=tupian_url,
                paixu=paixu,
                shangjia_zhuangtai=True,
                fengjin_zhuangtai=False,
                shenhe_zhuangtai=shenhe_status,
            )
            return Response({'code': 0, 'msg': '商品类型添加成功'})
        except Exception as e:
            logger.exception("添加商品类型失败")
            return Response({'code': 500, 'msg': '添加失败，请稍后重试'})

    @transaction.atomic
    def _update_type(self, dianpu, request):
        """修改店铺商品类型，支持更换图片（先删旧图）"""
        type_id = request.data.get('type_id') or request.POST.get('type_id')
        if not type_id:
            return Response({'code': 400, 'msg': '缺少 type_id'})

        try:
            obj = ShangpinLeixingDianpu.objects.select_for_update().get(
                id=type_id, dianpu_id=dianpu.id
            )
        except ShangpinLeixingDianpu.DoesNotExist:
            return Response({'code': 404, 'msg': '商品类型不存在'})
        except Exception as e:
            logger.exception("查询商品类型异常")
            return Response({'code': 500, 'msg': '服务器错误'})

        try:
            update_fields = []
            content_changed = False

            # 简介
            if 'jieshao' in request.data or 'jieshao' in request.POST:
                obj.jieshao = request.data.get('jieshao') or request.POST.get('jieshao')
                update_fields.append('jieshao')
                content_changed = True

            # 映射公共类型
            if 'gonggong_leixing_id' in request.data or 'gonggong_leixing_id' in request.POST:
                new_id = request.data.get('gonggong_leixing_id') or request.POST.get('gonggong_leixing_id')
                if not ShangpinLeixing.query.filter(id=new_id, shenhezhuangtai=1).exists():
                    return Response({'code': 400, 'msg': '公共商品类型无效'})
                obj.gonggong_leixing_id = new_id
                update_fields.append('gonggong_leixing_id')
                content_changed = True

            # 排序
            if 'paixu' in request.data or 'paixu' in request.POST:
                obj.paixu = request.data.get('paixu') or request.POST.get('paixu')
                update_fields.append('paixu')

            # 上架状态
            if 'shangjia_zhuangtai' in request.data or 'shangjia_zhuangtai' in request.POST:
                val = request.data.get('shangjia_zhuangtai') or request.POST.get('shangjia_zhuangtai')
                if isinstance(val, str):
                    val = val.lower() in ('true', '1', 'yes')
                obj.shangjia_zhuangtai = bool(val)
                update_fields.append('shangjia_zhuangtai')

            # 图片更换：先删除旧图，再上传新图
            image_file = request.FILES.get('image')
            if image_file:
                if obj.tupian_url:
                    delete_from_oss(obj.tupian_url)                # 删除旧图片
                file_path = f"dianpu/shangpin/shangpinleixing/{dianpu.id}_{int(time.time())}.png"
                full_url = upload_to_oss(image_file, file_path)
                if not full_url:
                    return Response({'code': 500, 'msg': '图片上传失败'})
                obj.tupian_url = full_url.replace(settings.COS_DOMAIN.rstrip('/') + '/', '', 1)
                update_fields.append('tupian_url')
                content_changed = True

            # 审核重置
            if content_changed:
                from shop.services.shenhe_config import is_kaiqi_shenhe_enabled
                shop_club = getattr(dianpu, 'club_id', None) or 'xq'
                if is_kaiqi_shenhe_enabled(shop_club):
                    obj.shenhe_zhuangtai = False
                    update_fields.append('shenhe_zhuangtai')

            if update_fields:
                obj.save(update_fields=update_fields)
            return Response({'code': 0, 'msg': '商品类型更新成功'})
        except Exception as e:
            logger.exception("修改商品类型失败")
            return Response({'code': 500, 'msg': '修改失败，请稍后重试'})

    @transaction.atomic
    def _delete_type(self, dianpu, request):
        """删除店铺商品类型，可选是否同时删除关联商品"""
        type_id = request.data.get('id') or request.POST.get('id')
        if not type_id:
            return Response({'code': 400, 'msg': '缺少类型ID'})

        try:
            obj = ShangpinLeixingDianpu.objects.select_for_update().get(
                id=type_id, dianpu_id=dianpu.id
            )
        except ShangpinLeixingDianpu.DoesNotExist:
            return Response({'code': 404, 'msg': '商品类型不存在'})
        except Exception as e:
            logger.exception("查询商品类型异常")
            return Response({'code': 500, 'msg': '服务器错误'})

        try:
            delete_products = request.data.get('delete_products') or request.POST.get('delete_products')
            delete_products = str(delete_products).lower() in ('true', '1', 'yes')

            if delete_products:
                # 删除该类型下所有关联商品（同时清理图片）
                products = Shangpin.query.filter(
                    dianpu_leixing_id=obj.id, dianpu_id=dianpu.id
                )
                for p in products:
                    if p.tupian_url:
                        delete_from_oss(p.tupian_url)
                    if p.guize_tupian:
                        delete_from_oss(p.guize_tupian)
                    p.delete()
            else:
                # 仅解除关联，不删商品
                Shangpin.query.filter(
                    dianpu_leixing_id=obj.id, dianpu_id=dianpu.id
                ).update(dianpu_leixing=None)

            # 删除类型自身图片
            if obj.tupian_url:
                delete_from_oss(obj.tupian_url)
            obj.delete()
            return Response({'code': 0, 'msg': '类型删除成功'})
        except Exception as e:
            logger.exception("删除商品类型失败")
            return Response({'code': 500, 'msg': '删除失败，请稍后重试'})

    # ---------- 专区操作 ----------
    @transaction.atomic
    def _add_zhuanqu(self, dianpu, request):
        """添加专区，自动从店铺商品类型获取 leixing_id（公共商品类型ID）"""
        try:
            mingzi = request.data.get('mingzi')
            dianpu_leixing_id = request.data.get('dianpu_leixing_id')
            paixu = request.data.get('paixu', 0)

            if not mingzi or not dianpu_leixing_id:
                return Response({'code': 400, 'msg': '缺少名称或所属商品类型'})

            # 获取店铺商品类型，并拿到映射的公共类型ID
            try:
                shop_type = ShangpinLeixingDianpu.query.get(
                    id=dianpu_leixing_id, dianpu_id=dianpu.id
                )
                leixing_id = shop_type.gonggong_leixing_id   # 这就是专区需要的 leixing_id
            except ShangpinLeixingDianpu.DoesNotExist:
                return Response({'code': 400, 'msg': '所选商品类型无效'})

            # 验证公共类型有效
            if not ShangpinLeixing.query.filter(id=leixing_id, shenhezhuangtai=1).exists():
                return Response({'code': 400, 'msg': '关联的公共商品类型无效'})

            ShangpinZhuanqu.query.create(
                dianpu_id=dianpu.id,
                mingzi=mingzi,
                dianpu_leixing_id=dianpu_leixing_id,
                leixing_id=leixing_id,                     # 自动填充
                paixu=paixu,
                shangjia_zhuangtai=True,
                fengjin_zhuangtai=False,
            )
            return Response({'code': 0, 'msg': '专区添加成功'})
        except Exception as e:
            logger.exception("添加专区失败")
            return Response({'code': 500, 'msg': '添加失败，请稍后重试'})

    @transaction.atomic
    def _update_zhuanqu(self, dianpu, request):
        """修改专区，若更换所属商品类型则同步更新 leixing_id"""
        zhuanqu_id = request.data.get('zhuanqu_id')
        if not zhuanqu_id:
            return Response({'code': 400, 'msg': '缺少 zhuanqu_id'})

        try:
            obj = ShangpinZhuanqu.objects.select_for_update().get(
                id=zhuanqu_id, dianpu_id=dianpu.id
            )
        except ShangpinZhuanqu.DoesNotExist:
            return Response({'code': 404, 'msg': '专区不存在'})
        except Exception as e:
            logger.exception("查询专区异常")
            return Response({'code': 500, 'msg': '服务器错误'})

        try:
            update_fields = []

            if 'mingzi' in request.data:
                obj.mingzi = request.data.get('mingzi')
                update_fields.append('mingzi')

            if 'dianpu_leixing_id' in request.data:
                new_id = request.data.get('dianpu_leixing_id')
                try:
                    shop_type = ShangpinLeixingDianpu.query.get(
                        id=new_id, dianpu_id=dianpu.id
                    )
                    obj.dianpu_leixing_id = new_id
                    obj.leixing_id = shop_type.gonggong_leixing_id   # 同步更新公共类型ID
                    update_fields.extend(['dianpu_leixing_id', 'leixing_id'])
                except ShangpinLeixingDianpu.DoesNotExist:
                    return Response({'code': 400, 'msg': '所选商品类型无效'})

            if 'paixu' in request.data:
                obj.paixu = request.data.get('paixu')
                update_fields.append('paixu')

            if 'shangjia_zhuangtai' in request.data:
                val = request.data.get('shangjia_zhuangtai')
                if isinstance(val, str):
                    val = val.lower() in ('true', '1', 'yes')
                obj.shangjia_zhuangtai = bool(val)
                update_fields.append('shangjia_zhuangtai')

            if update_fields:
                obj.save(update_fields=update_fields)
            return Response({'code': 0, 'msg': '专区更新成功'})
        except Exception as e:
            logger.exception("修改专区失败")
            return Response({'code': 500, 'msg': '修改失败，请稍后重试'})

    @transaction.atomic
    def _delete_zhuanqu(self, dianpu, request):
        """删除专区，可选是否同时删除关联商品"""
        zhuanqu_id = request.data.get('id')
        if not zhuanqu_id:
            return Response({'code': 400, 'msg': '缺少专区ID'})

        try:
            obj = ShangpinZhuanqu.objects.select_for_update().get(
                id=zhuanqu_id, dianpu_id=dianpu.id
            )
        except ShangpinZhuanqu.DoesNotExist:
            return Response({'code': 404, 'msg': '专区不存在'})
        except Exception as e:
            logger.exception("查询专区异常")
            return Response({'code': 500, 'msg': '服务器错误'})

        try:
            delete_products = request.data.get('delete_products')
            delete_products = str(delete_products).lower() in ('true', '1', 'yes')

            if delete_products:
                products = Shangpin.query.filter(
                    zhuanqu_id=obj.id, dianpu_id=dianpu.id
                )
                for p in products:
                    if p.tupian_url:
                        delete_from_oss(p.tupian_url)
                    if p.guize_tupian:
                        delete_from_oss(p.guize_tupian)
                    p.delete()
            else:
                Shangpin.query.filter(
                    zhuanqu_id=obj.id, dianpu_id=dianpu.id
                ).update(zhuanqu_id=None)

            obj.delete()
            return Response({'code': 0, 'msg': '专区删除成功'})
        except Exception as e:
            logger.exception("删除专区失败")
            return Response({'code': 500, 'msg': '删除失败，请稍后重试'})



class ShopProductListView(APIView):
    """
    商品列表接口，支持筛选、分页。
    URL: /shangdian/sdhqspsj
    权限: JWT认证 + 店铺验证
    """
    permission_classes = [IsAuthenticated]

    def post(self, request):
        # 1. 身份验证，获取店铺对象
        frontend_user_id = request.data.get('userId')
        if not frontend_user_id:
            return Response({'code': 400, 'msg': '缺少必要参数 userId'})

        dianpu, error = verify_shop_permission(request, frontend_user_id)
        if error:
            return error

        # 2. 安全解析分页与筛选参数
        try:
            page = int(request.data.get('page', 1))
            page_size = int(request.data.get('page_size', 20))
        except (TypeError, ValueError):
            return Response({'code': 400, 'msg': '分页参数格式错误'})

        keyword = str(request.data.get('keyword', '')).strip()
        shop_product_type_id = request.data.get('shop_product_type_id')  # 店铺商品类型ID
        zhuanqu_id = request.data.get('zhuanqu_id')                     # 专区ID

        # 布尔型筛选字段
        def parse_bool(val):
            if val is None or val == '':
                return None
            if isinstance(val, bool):
                return val
            if isinstance(val, str):
                return val.lower() in ('true', '1', 'yes')
            return bool(val)

        shenhe = parse_bool(request.data.get('shenhe_zhuangtai'))
        shangjia = parse_bool(request.data.get('shangjia_zhuangtai'))
        fengjin = parse_bool(request.data.get('fengjin_zhuangtai'))

        # 3. 构建查询（只查当前店铺的商品）
        products = Shangpin.query.filter(dianpu_id=dianpu.id).select_related(
            'dianpu_leixing'
        ).only(
            'id', 'biaoqian', 'jiage', 'kucun', 'leixing_id', 'zhuanqu_id',
            'zhenshi_xiaoliang', 'duiwai_xiaoliang', 'jieshao', 'xiadan_xuzhi',
            'guize_tupian', 'yaoqiuleixing', 'huiyuan_id', 'yongjin',
            'tupian_url', 'ewai_dashou_fencheng', 'paixu',
            'dianpu_leixing_id', 'shangjia_zhuangtai', 'fengjin_zhuangtai',
            'shenhe_zhuangtai', 'CreateTime', 'UpdateTime'
        )

        # 筛选
        if shop_product_type_id is not None:
            try:
                products = products.filter(dianpu_leixing_id=int(shop_product_type_id))
            except (ValueError, TypeError):
                return Response({'code': 400, 'msg': 'shop_product_type_id 格式错误'})

        if zhuanqu_id is not None:
            try:
                products = products.filter(zhuanqu_id=int(zhuanqu_id))
            except (ValueError, TypeError):
                return Response({'code': 400, 'msg': 'zhuanqu_id 格式错误'})

        if shenhe is not None:
            products = products.filter(shenhe_zhuangtai=shenhe)
        if shangjia is not None:
            products = products.filter(shangjia_zhuangtai=shangjia)
        if fengjin is not None:
            products = products.filter(fengjin_zhuangtai=fengjin)

        # 关键词搜索（商品ID、标题、介绍）
        if keyword:
            products = products.filter(
                models.Q(id__icontains=keyword) |
                models.Q(biaoqian__icontains=keyword) |
                models.Q(jieshao__icontains=keyword)
            )

        # 4. 分页
        total_count = products.count()
        paginator = Paginator(products, page_size)
        page_obj = paginator.get_page(page)

        # 5. 构造返回数据
        product_list = []
        for p in page_obj:
            product_list.append({
                'id': p.id,
                'biaoqian': p.biaoqian or '',
                'jiage': p.jiage,
                'kucun': p.kucun,
                'leixing_id': p.leixing_id,
                'zhuanqu_id': p.zhuanqu_id,
                'zhenshi_xiaoliang': p.zhenshi_xiaoliang,
                'duiwai_xiaoliang': p.duiwai_xiaoliang,
                'jieshao': p.jieshao or '',
                'xiadan_xuzhi': p.xiadan_xuzhi or '',
                'guize_tupian': p.guize_tupian or '',
                'yaoqiuleixing': p.yaoqiuleixing,
                'huiyuan_id': p.huiyuan_id or '',
                'yongjin': p.yongjin,
                'tupian_url': p.tupian_url or '',
                'ewai_dashou_fencheng': p.ewai_dashou_fencheng,
                'paixu': p.paixu,
                'dianpu_leixing_id': p.dianpu_leixing_id,
                'shangjia_zhuangtai': p.shangjia_zhuangtai,
                'fengjin_zhuangtai': p.fengjin_zhuangtai,
                'shenhe_zhuangtai': p.shenhe_zhuangtai,
                'CreateTime': p.CreateTime.isoformat() if p.CreateTime else '',
                'UpdateTime': p.UpdateTime.isoformat() if p.UpdateTime else '',
            })

        return Response({
            'code': 0,
            'data': {
                'list': product_list,
                'total': total_count,
            }
        })



class ShopProductModifyView1(APIView):
    """
    商品统一操作：修改、添加、删除
    URL: /shangdian/xgdpsplx1
    """
    permission_classes = [IsAuthenticated]

    def post(self, request):
        frontend_user_id = request.data.get('userId')
        if not frontend_user_id:
            return Response({'code': 400, 'msg': '缺少必要参数 userId'})

        dianpu, error = verify_shop_permission(request, frontend_user_id)
        if error:
            return error

        action = request.data.get('action')
        if not action:
            return Response({'code': 400, 'msg': '缺少操作类型 action'})

        if action == 'update_product':
            return self._update_product(dianpu, request.data, request.FILES)
        elif action == 'add_product':
            return self._add_product(dianpu, request.data, request.FILES)
        elif action == 'delete_product':
            return self._delete_product(dianpu, request.data)
        else:
            return Response({'code': 400, 'msg': '不支持的操作类型'})

    # ---------- 修改商品 ----------
    @transaction.atomic
    def _update_product(self, dianpu, data, files):
        product_id = data.get('product_id')
        if not product_id:
            return Response({'code': 400, 'msg': '缺少 product_id'})

        try:
            product = Shangpin.objects.select_for_update().get(id=product_id, dianpu_id=dianpu.id)
        except Shangpin.DoesNotExist:
            return Response({'code': 404, 'msg': '商品不存在'})

        update_fields = []
        content_changed = False

        # 辅助函数：安全转换为整数，失败则返回原值（让其报错）
        def to_int(val):
            try:
                return int(val)
            except (TypeError, ValueError):
                return val

        def to_float(val):
            try:
                return float(val)
            except (TypeError, ValueError):
                return val

        # 标题
        if 'biaoqian' in data:
            product.biaoqian = data['biaoqian']
            update_fields.append('biaoqian')
            content_changed = True

        # 价格
        if 'jiage' in data:
            product.jiage = to_float(data['jiage'])
            update_fields.append('jiage')
            content_changed = True

        # 库存
        if 'kucun' in data:
            product.kucun = to_int(data['kucun'])
            update_fields.append('kucun')
            content_changed = True

        # 店铺商品类型
        if 'dianpu_leixing_id' in data:
            new_type_id = to_int(data['dianpu_leixing_id'])
            if not ShangpinLeixingDianpu.query.filter(id=new_type_id, dianpu_id=dianpu.id).exists():
                return Response({'code': 400, 'msg': '无效的店铺商品类型'})
            product.dianpu_leixing_id = new_type_id
            update_fields.append('dianpu_leixing_id')
            content_changed = True

        # 专区
        if 'zhuanqu_id' in data:
            new_zq_id = data['zhuanqu_id']
            if new_zq_id is not None and new_zq_id != '':
                new_zq_id = to_int(new_zq_id)
                if not ShangpinZhuanqu.query.filter(id=new_zq_id, dianpu_id=dianpu.id).exists():
                    return Response({'code': 400, 'msg': '无效的专区'})
                product.zhuanqu_id = new_zq_id
            else:
                product.zhuanqu_id = None
            update_fields.append('zhuanqu_id')
            content_changed = True

        # 介绍
        if 'jieshao' in data:
            product.jieshao = data['jieshao']
            update_fields.append('jieshao')
            content_changed = True

        # 下单须知
        if 'xiadan_xuzhi' in data:
            product.xiadan_xuzhi = data['xiadan_xuzhi']
            update_fields.append('xiadan_xuzhi')

        # ★ 抢单要求类型及会员/佣金自动处理
        if 'yaoqiuleixing' in data:
            yqlx = to_int(data['yaoqiuleixing'])
            if yqlx not in [1, 2]:
                return Response({'code': 400, 'msg': '抢单要求类型无效'})
            product.yaoqiuleixing = yqlx
            update_fields.append('yaoqiuleixing')
            content_changed = True

            if yqlx == 1:
                # 会员抢单：优先使用前端显式传递的非空会员ID
                if 'huiyuan_id' in data and data.get('huiyuan_id'):
                    product.huiyuan_id = data['huiyuan_id']
                    update_fields.append('huiyuan_id')
                    product.yongjin = None
                    if 'yongjin' not in update_fields:
                        update_fields.append('yongjin')
                else:
                    # 自动从公共类型获取会员ID，或转为佣金
                    try:
                        shop_type = ShangpinLeixingDianpu.query.select_related('gonggong_leixing').get(
                            id=product.dianpu_leixing_id, dianpu_id=dianpu.id
                        )
                        public_type = shop_type.gonggong_leixing
                        if not public_type:
                            raise ShangpinLeixing.DoesNotExist
                        auto_huiyuan_id = public_type.huiyuan_id
                        if auto_huiyuan_id:
                            product.huiyuan_id = auto_huiyuan_id
                            update_fields.append('huiyuan_id')
                            product.yongjin = None
                            if 'yongjin' not in update_fields:
                                update_fields.append('yongjin')
                        elif public_type.yaoqiuleixing == 2 and public_type.yongjin:
                            # 无会员，强制转为佣金
                            product.yaoqiuleixing = 2
                            product.yongjin = public_type.yongjin
                            product.huiyuan_id = None
                            # yaoqiuleixing 已在 update_fields 中，需要添加 huiyuan_id 和 yongjin
                            update_fields.append('huiyuan_id')
                            update_fields.append('yongjin')
                        else:
                            return Response({'code': 400, 'msg': '会员抢单缺少会员ID，公共类型也无会员ID或佣金'})
                    except (ShangpinLeixingDianpu.DoesNotExist, ShangpinLeixing.DoesNotExist):
                        return Response({'code': 400, 'msg': '店铺商品类型无效'})
            elif yqlx == 2:
                # 佣金抢单，清除会员ID，设置佣金
                product.huiyuan_id = None
                update_fields.append('huiyuan_id')
                if 'yongjin' in data:
                    product.yongjin = to_float(data['yongjin']) or 0
                else:
                    product.yongjin = 0
                update_fields.append('yongjin')
        else:
            # 未修改抢单类型，保留原有独立修改逻辑
            if 'huiyuan_id' in data:
                product.huiyuan_id = data['huiyuan_id'] or None
                update_fields.append('huiyuan_id')
                content_changed = True
            if 'yongjin' in data:
                product.yongjin = to_float(data['yongjin']) or 0
                update_fields.append('yongjin')
                content_changed = True

        # 打手额外分成金额
        if 'ewai_dashou_fencheng' in data:
            fencheng = to_float(data['ewai_dashou_fencheng']) or 0

            
            if fencheng > (product.jiage or 0):
                return Response({'code': 400, 'msg': '分成金额不能超过商品价格'})
            product.ewai_dashou_fencheng = fencheng
            update_fields.append('ewai_dashou_fencheng')
            content_changed = True

        # 排序
        if 'paixu' in data:
            product.paixu = to_int(data['paixu'])
            update_fields.append('paixu')

        # 上架状态（保持原逻辑，兼容字符串）
        if 'shangjia_zhuangtai' in data:
            val = data['shangjia_zhuangtai']
            if isinstance(val, str):
                val = val.lower() in ('true', '1', 'yes')
            product.shangjia_zhuangtai = bool(val)
            update_fields.append('shangjia_zhuangtai')

        # ★ 商品图片真上传
        image_file = files.get('image')
        if image_file:
            if product.tupian_url:
                delete_from_oss(product.tupian_url)
            file_path = f"dianpu/shangpin/shangpin/{dianpu.id}_{int(time.time())}.png"
            full_url = upload_to_oss(image_file, file_path)
            if not full_url:
                return Response({'code': 500, 'msg': '商品图片上传失败'})
            product.tupian_url = full_url.replace(settings.COS_DOMAIN.rstrip('/') + '/', '', 1)
            update_fields.append('tupian_url')
            content_changed = True

        # ★ 规则图片真上传
        rule_file = files.get('rule_image')
        remove_rule = data.get('remove_rule_image', '0')
        if rule_file:
            if product.guize_tupian:
                delete_from_oss(product.guize_tupian)
            file_path = f"dianpu/shangpin/shangpinguize/{dianpu.id}_{int(time.time())}.png"
            full_url = upload_to_oss(rule_file, file_path)
            if full_url:
                product.guize_tupian = full_url.replace(settings.COS_DOMAIN.rstrip('/') + '/', '', 1)
                update_fields.append('guize_tupian')
                content_changed = True
        elif remove_rule == '1' and product.guize_tupian:
            delete_from_oss(product.guize_tupian)
            product.guize_tupian = None
            update_fields.append('guize_tupian')
            content_changed = True

        if content_changed:
            from shop.services.shenhe_config import is_kaiqi_shenhe_enabled
            shop_club = getattr(dianpu, 'club_id', None) or 'xq'
            if is_kaiqi_shenhe_enabled(shop_club):
                product.shenhe_zhuangtai = False
                update_fields.append('shenhe_zhuangtai')

        if update_fields:
            product.save(update_fields=update_fields + ['UpdateTime'])
        return Response({'code': 0, 'msg': '商品修改成功'})

    # ---------- 添加商品（增强会员/佣金默认逻辑） ----------
    @transaction.atomic
    def _add_product(self, dianpu, data, files):
        biaoqian = data.get('biaoqian')
        jiage = data.get('jiage')
        kucun = data.get('kucun')
        dianpu_leixing_id = data.get('dianpu_leixing_id')
        zhuanqu_id = data.get('zhuanqu_id')
        jieshao = data.get('jieshao')

        if not all([biaoqian, jiage is not None, kucun is not None, dianpu_leixing_id, zhuanqu_id, jieshao]):
            return Response({'code': 400, 'msg': '必填项缺失'})

        try:
            shop_type = ShangpinLeixingDianpu.query.select_related('gonggong_leixing').get(id=dianpu_leixing_id, dianpu_id=dianpu.id)
        except ShangpinLeixingDianpu.DoesNotExist:
            return Response({'code': 400, 'msg': '无效的店铺商品类型'})

        public_type = shop_type.gonggong_leixing
        if not public_type or public_type.shenhezhuangtai != 1:
            return Response({'code': 400, 'msg': '关联的公共商品类型无效'})

        # 商品图片上传
        image_file = files.get('image')
        if not image_file:
            return Response({'code': 400, 'msg': '必须上传商品图片'})
        file_path = f"dianpu/shangpin/shangpin/{dianpu.id}_{int(time.time())}.png"
        full_url = upload_to_oss(image_file, file_path)
        if not full_url:
            return Response({'code': 500, 'msg': '商品图片上传失败'})
        tupian_url = full_url.replace(settings.COS_DOMAIN.rstrip('/') + '/', '', 1)

        # 规则图片
        guize_tupian = None
        rule_file = files.get('rule_image')
        if rule_file:
            file_path = f"dianpu/shangpin/shangpinguize/{dianpu.id}_{int(time.time())}.png"
            full_url = upload_to_oss(rule_file, file_path)
            if full_url:
                guize_tupian = full_url.replace(settings.COS_DOMAIN.rstrip('/') + '/', '', 1)

        yaoqiuleixing = int(data.get('yaoqiuleixing', 1))
        if yaoqiuleixing == 1:
            huiyuan_id = data.get('huiyuan_id')
            # 如果前端没传有效的会员ID，尝试从公共类型获取
            if not huiyuan_id:
                huiyuan_id = public_type.huiyuan_id
            # 仍然没有会员ID，检查公共类型是否可转为佣金
            if not huiyuan_id:
                if public_type.yaoqiuleixing == 2 and public_type.yongjin:
                    # 自动转为佣金抢单
                    yaoqiuleixing = 2
                    yongjin = public_type.yongjin
                    huiyuan_id = None
                else:
                    return Response({'code': 400, 'msg': '会员抢单缺少会员ID，且无法自动获取'})
            else:
                yongjin = None
        else:
            huiyuan_id = None
            yongjin = data.get('yongjin') or public_type.yongjin or 0

        ewai_fencheng = data.get('ewai_dashou_fencheng') or 0


        try:
            ewai_val = float(ewai_fencheng)
            jiage_val = float(jiage)
            if ewai_val > jiage_val:
                return Response({'code': 400, 'msg': '分成金额不能超过商品价格'})
        except ValueError:
            # 处理转换失败的情况，比如记录日志或设为默认值
            print("无法转换为数字")
        


       
        '''if ewai_fencheng > jiage:
            return Response({'code': 400, 'msg': '分成金额不能超过商品价格'})'''

        shenhe_status = True
        from shop.services.shenhe_config import is_kaiqi_shenhe_enabled
        shop_club = getattr(dianpu, 'club_id', None) or 'xq'
        if is_kaiqi_shenhe_enabled(shop_club):
            shenhe_status = False

        product = Shangpin.query.create(
            biaoqian=biaoqian,
            jiage=jiage,
            kucun=kucun,
            dianpu_id=dianpu.id,
            dianpu_leixing_id=dianpu_leixing_id,
            zhuanqu_id=zhuanqu_id,
            leixing_id=public_type.id,
            jieshao=jieshao,
            xiadan_xuzhi=data.get('xiadan_xuzhi', ''),
            guize_tupian=guize_tupian,
            tupian_url=tupian_url,
            yaoqiuleixing=yaoqiuleixing,
            huiyuan_id=huiyuan_id,
            yongjin=yongjin,
            ewai_dashou_fencheng=ewai_fencheng,
            kaioi_ewai_dashou_fencheng=True,
            paixu=data.get('paixu', 0),
            shangjia_zhuangtai=data.get('shangjia_zhuangtai', True),
            fengjin_zhuangtai=False,
            shenhe_zhuangtai=shenhe_status,
            shenhezhuangtai=1,
        )
        return Response({'code': 0, 'msg': '商品添加成功', 'product_id': product.id})

    # ---------- 删除商品（完全不变） ----------
    @transaction.atomic
    def _delete_product(self, dianpu, data):
        product_id = data.get('product_id')
        if not product_id:
            return Response({'code': 400, 'msg': '缺少 product_id'})

        try:
            product = Shangpin.objects.select_for_update().get(id=product_id, dianpu_id=dianpu.id)
        except Shangpin.DoesNotExist:
            return Response({'code': 404, 'msg': '商品不存在'})

        if product.tupian_url:
            delete_from_oss(product.tupian_url)
        if product.guize_tupian:
            delete_from_oss(product.guize_tupian)

        product.delete()
        return Response({'code': 0, 'msg': '商品已删除'})

