from rest_framework import viewsets
from utils.page import MyPageNumberPagination
from utils.datasolve import sumOfList, transportation_calculate
from utils.md5 import Md5
from rest_framework.filters import OrderingFilter
from django_filters.rest_framework import DjangoFilterBackend
from django.db import transaction
from rest_framework.response import Response
from rest_framework.exceptions import APIException
from django.utils import timezone
from django.db.models import Sum
from .models import BoundListModel, BoundDetailModel,BoundBatchModel, BatchLogModel, OutBatchModel,OutBoundDetailModel,MaterialStatistics,OutBoundDemandModel
# from .files import FileListRenderCN, FileDetailRenderCN

from .serializers import BoundListGetSerializer,BoundListPostSerializer,BoundBatchGetSerializer,BoundBatchPostSerializer,BoundDetailGetSerializer,BoundDetailPostSerializer
from .serializers import OutBoundDetailGetSerializer,OutBoundDetailPostSerializer,OutBatchGetSerializer,OutBatchPostSerializer,BatchLogGetSerializer
from .serializers import MaterialStatisticsSerializer,MaterialStatisticsSerializer_items
from .serializers import OutBoundDemandModelSerializer
from .filter import BoundListFilter, BoundDetailFilter,BoundBatchFilter
from .filter import OutBatchFilter,OutBoundDetailFilter,BatchlogFilter
from .filter import MaterialStatisticsFilter
from .filter import OutBoundDemandFilter
# 以后添加模块检验
from warehouse.models import ListModel as warehouse
from staff.models import ListModel as staff
from rest_framework.permissions import AllowAny
from rest_framework.views import APIView

# 出库需求视图类
class OutBoundDemandViewSet(viewsets.ModelViewSet):
    """
        retrieve:
            Response a data list(get)
        list:
            Response a data list(all)
        create:
            Create a data line(post)

        delete:
            Delete a data line(delete)

    """
    # authentication_classes = []  # 禁用所有认证类
    # permission_classes = [AllowAny]  # 允许任意访问
    
    pagination_class = MyPageNumberPagination
    filter_backends = [DjangoFilterBackend, OrderingFilter, ]
    ordering_fields = ['id', "create_time", "update_time", ]
    filter_class = OutBoundDemandFilter
    def get_project(self):
        try:
            id = self.kwargs.get('pk')
            return id
        except:
            return None

    def get_queryset(self):
        id = self.get_project()
        if self.request.user:
            if id is None:
                return OutBoundDemandModel.objects.filter( is_delete=False)
            else:
                return OutBoundDemandModel.objects.filter( id=id, is_delete=False)
        else:
            return OutBoundDemandModel.objects.none()

    def get_serializer_class(self):
        if self.action in ['list' ]:
            return OutBoundDemandModelSerializer
        else:
            return OutBoundDemandModelSerializer
    
    def batch_list(self, request):
        data =self.request.data
        OutBoundDemand_all = OutBoundDemandModel.objects.filter(bound_list_id=data['bound_list_id'], is_delete=False).all()
        data = OutBoundDemandModelSerializer(OutBoundDemand_all, many=True).data
        return_data ={
                "code": 200,
                "msg": "Success Create",
            	"data": data
        }
    
        return Response(return_data,status=200,headers={})

  
    def create(self, request, *args, **kwargs):
        data = self.request.data

        data['openid'] = self.request.auth.openid
        data['create_time'] = str(timezone.now().strftime('%Y-%m-%d %H:%M:%S'))
        data['update_time'] = str(timezone.now().strftime('%Y-%m-%d %H:%M:%S'))
        data['working'] = True
        bound_list_obj = BoundListModel.objects.get(id=data['bound_list_id'])

        OutBoundDemand_obj =OutBoundDemandModel.objects.create(
            bound_list=bound_list_obj, 
            goods_code=data['goods_code'], 
            goods_desc=data['goods_desc'], 
            goods_std=data['goods_std'], 
            goods_unit=data['goods_unit'], 
            goods_qty=data['goods_out_qty'],
            out_type = data['out_type'],
            creater=data['creater'], 
            create_time=data['create_time'],
            update_time=data['update_time'], 
            working=data['working']
            )
        return_data = OutBoundDemandModelSerializer(OutBoundDemand_obj).data
        headers = self.get_success_headers(return_data)

        return Response(return_data, status=200, headers=headers)
    
    def batch_demanded_list(self, request):
        data =self.request.data
        OutBoundDemand_all = OutBatchModel.objects.filter(bound_list_id=data['bound_list_id'], is_delete=False).all()
        data = OutBatchGetSerializer(OutBoundDemand_all, many=True).data
        return_data = {
            "code": 200,
            "msg": "Success Create",
            "data": data
        }

        return Response(return_data,status=200,headers={})

    def distribute(self, request):
        """主分配入口"""
        try:
            with transaction.atomic():
                bound_list_id, demands,out_type, creater= self.validate_distribute_request(request)

                if OutBatchModel.objects.filter(bound_list_id=bound_list_id, is_delete=False).exists():
                    return_data = {
                        "code": 200,
                        "msg": "Success Create",
                        "data": {
                            "msg": "该订单已分配,请勿重复分配"
                        }
                    }
                    return Response(return_data, status=200, headers={})
                aggregated_demands = self.aggregate_demands(demands)
                result = self.process_all_goods(aggregated_demands, request, out_type, creater,bound_list_id)
                return self.build_success_response(result)
        except APIException as e:
            return self.build_error_response(e.detail, 200)
        except Exception as e:
            return self.build_error_response(str(e), 200)

    # 验证层方法
    def validate_distribute_request(self, request):
        """验证请求参数"""
        bound_list_id = request.data.get('bound_list_id')
        if not bound_list_id:
            raise APIException({"detail": "Missing bound_list_id"})

        demands = OutBoundDemandModel.objects.filter(
            bound_list_id=bound_list_id,
            is_delete=False
        )
        if not demands.exists():
            raise APIException({"detail": "No demands found"})
        base_info = OutBoundDemandModel.objects.filter(
            bound_list_id=bound_list_id,
            is_delete=False
        ).first()
        out_type = base_info.out_type
        creater = base_info.creater

        return bound_list_id, demands, out_type, creater

    # 数据处理层方法
    def aggregate_demands(self, demands):
        """合并相同物料需求"""
        return demands.values('goods_code').annotate(
            total_demand=Sum('goods_qty')
        )

    # 核心分配逻辑
    def process_all_goods(self, aggregated_demands, request, out_type, creater,bound_list_id):
        """处理所有物料分配"""
        return [
            self.process_single_goods(
                goods_code=item['goods_code'],
                total_demand=item['total_demand'],
                request=request,
                out_type=out_type,
                creater=creater,
                bound_list_id=bound_list_id

            )
            for item in aggregated_demands
        ]

    def process_single_goods(self, goods_code, total_demand, request,out_type, creater,bound_list_id):
        """处理单个物料分配"""
        batches = self.get_available_batches(goods_code)
        remaining, allocations = self.allocate_batches(total_demand, batches, request,out_type, creater,bound_list_id)
        
        if remaining > 0:
            raise APIException({
                "detail": f"Insufficient stock for {goods_code}",
                "required": total_demand,
                "allocated": total_demand - remaining
            })
        
        return {
            "goods_code": goods_code,
            "total_demand": total_demand,
            "allocations": allocations
        }

    def get_available_batches(self, goods_code):
        """获取可用入库批次"""
        return BoundBatchModel.objects.filter(
            goods_code=goods_code,
            is_delete=False
        ).order_by('bound_batch_order')

    # 批次分配逻辑
    def allocate_batches(self, total_demand, batches, request,out_type, creater,bound_list_id):
        """分配具体批次"""
        remaining = total_demand
        allocations = []
        
        for batch in batches:
            if remaining <= 0:
                break
            
            allocated = self.allocate_single_batch(
                batch=batch,
                remaining=remaining,
                request=request,
                out_type=out_type,
                creater=creater,
                bound_list_id=bound_list_id

            )
            
            if allocated == 0:
                continue
                
            allocations.append(allocated)
            remaining -= allocated['allocated']
        
        return remaining, allocations

    def allocate_single_batch(self, batch, remaining, request,out_type, creater,bound_list_id):
        """单个批次分配逻辑"""
        available = batch.goods_in_location_qty - batch.goods_out_qty
        if available <= 0:
            return 0

        allocate_qty = min(remaining, available)
        self.update_batch_status(batch, allocate_qty)
        out_batch = self.create_out_batch(batch, allocate_qty, request,out_type, creater,bound_list_id)
        
        return {
            "batch": batch.bound_number,
            "allocated": allocate_qty,
            "out_batch": out_batch.out_number
        }

    # 数据操作层方法
    def update_batch_status(self, batch, allocate_qty):
        """更新批次状态和数量"""
        batch.goods_out_qty += allocate_qty
        
        if batch.goods_out_qty == batch.goods_in_location_qty:
            batch.status = 6  # 已出库
        elif batch.goods_out_qty > 0:
            batch.status = 5  # 部分出库
            
        batch.save()

    def create_out_batch(self, batch, allocate_qty, request,out_type, creater,bound_list_id):
        """创建出库记录"""
        out_data = {
            'bound_list': bound_list_id,
            'out_number': self.generate_out_number(batch.goods_code),
            'batch_number': batch.id,
            'out_date': timezone.now(),
            'warehouse_code': batch.warehouse_code,
            'warehouse_name': batch.warehouse_name,
            'goods_code': batch.goods_code,
            'goods_desc': batch.goods_desc,
            'goods_out_qty': allocate_qty,
            'status': 0,
            'openid': request.auth.openid,
            'out_type': out_type,
            'creater': creater,


        }
        
        serializer = OutBatchPostSerializer(data=out_data)
        if not serializer.is_valid():
            raise APIException({
                "detail": f"Serialization error for {batch.goods_code}",
                "errors": serializer.errors
            })
            
        return serializer.save()

    # 工具方法
    def generate_out_number(self, goods_code):
        """生成唯一出库单号"""
        timestamp = timezone.now().strftime("%Y%m%d%H%M%S")
        import uuid

        return f"OUT-{goods_code}-{timestamp}-{uuid.uuid4().hex[:6]}"

    def build_success_response(self, data):
        """构建成功响应"""
        return Response({
            "code": 200,
            "msg": "Distribution completed",
            "data": data
        })

    def build_error_response(self, error, status_code):
        """构建错误响应"""
        return Response({
            "code": status_code,
            "msg": "Distribution failed" if status_code == 400 else "Server error",
            "error": error
        }, status=status_code)

# 物料统计视图类
class MaterialStatisticsViewSet(viewsets.ModelViewSet):
    """
        retrieve:
            Response a data list(get)
        list:
            Response a data list(all)
        create:
            Create a data line(post)

        delete:
            Delete a data line(delete)

    """
    # authentication_classes = []  # 禁用所有认证类
    # permission_classes = [AllowAny]  # 允许任意访问
    
    pagination_class = MyPageNumberPagination
    filter_backends = [DjangoFilterBackend, OrderingFilter, ]
    ordering_fields = ['id', "create_time", "update_time", ]
    filter_class = MaterialStatisticsFilter

    def get_project(self):
        try:
            id = self.kwargs.get('pk')
            return id
        except:
            return None

    def get_queryset(self):
        id = self.get_project()
        if self.request.user:
            if id is None:
                return MaterialStatistics.objects.filter()
            else:
                return MaterialStatistics.objects.filter(id=id)
        else:
            return MaterialStatistics.objects.none()

    def get_serializer_class(self):
        if self.action in ['list' ]:
            return MaterialStatisticsSerializer
        elif self.action in ['retrieve']:
            return MaterialStatisticsSerializer_items
        else:
            return self.http_method_not_allowed(request=self.request)

# 汇报单类视图
class BoundListViewSet(viewsets.ModelViewSet):
    """
        retrieve:
            Response a data list(get)
        list:
            Response a data list(all)
        create:
            Create a data line(post)

        delete:
            Delete a data line(delete)

    """
    # authentication_classes = []  # 禁用所有认证类
    # permission_classes = [AllowAny]  # 允许任意访问
    
    pagination_class = MyPageNumberPagination
    filter_backends = [DjangoFilterBackend, OrderingFilter, ]
    ordering_fields = ['id', "create_time", "update_time", ]
    filter_class = BoundListFilter

    def get_project(self):
        try:
            id = self.kwargs.get('pk')
            return id
        except:
            return None

    def get_queryset(self):
        id = self.get_project()
        if self.request.user:
            if id is None:
                return BoundListModel.objects.filter( is_delete=False)
            else:
                return BoundListModel.objects.filter( id=id, is_delete=False)
        else:
            return BoundListModel.objects.none()

    def get_serializer_class(self):
        if self.action in ['list', 'destroy','retrieve']:
            return BoundListGetSerializer
        elif self.action in ['create', 'update']:
            return BoundListPostSerializer
        else:
            return self.http_method_not_allowed(request=self.request)

    def create(self, request, *args, **kwargs):

        data = self.request.data
        # if BoundListModel.objects.filter(code=data['code'], is_delete=False).exists():
        #     raise APIException({"detail": "Data exists"})
        # else:
        data['openid'] = self.request.auth.openid
        data['bound_date'] =str(timezone.now().strftime('%Y-%m-%d'))
        order_day=str(timezone.now().strftime('%Y-%m-'))
        data['bound_month'] =str(timezone.now().strftime('%Y%m'))
        if data['bound_type'] == 'in':
            data['bound_status'] = '100'
        else:
            data['bound_status'] = '200'
        

        qs_set = BoundListModel.objects.filter(bound_month=data['bound_month'], bound_code_type=data['bound_code_type'], is_delete=False)
        print('qs_set是:', len(qs_set))
        if len(qs_set) > 0:
            bound_last_code = qs_set.order_by('-id').first().bound_code
            data['bound_code'] = data['bound_code_type'] +'-'+ order_day + str(int(bound_last_code.split('-')[-1])+1).zfill(4)
        else:
            data['bound_code'] = data['bound_code_type'] +'-'+ order_day + '0001'

        serializer = self.get_serializer(data=data)
        serializer.is_valid(raise_exception=True)
        serializer.save()

        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=200, headers=headers)
    
    def update(self, request, pk):
        qs = self.get_object()
        data = self.request.data
        serializer = self.get_serializer(qs, data=data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=200, headers=headers)


    def destroy(self, request, pk):
        qs = self.get_object()
        if qs.openid != self.request.auth.openid:
            raise APIException({"detail": "该入库非您所属,禁止删除,您可以进行编辑"})
        else:
            qs.is_delete = True
            qs.bound_code =qs.bound_code+'-delete'+str(timezone.now().strftime('%Y%m%d%H%M%S'))
            qs.save()
            serializer = self.get_serializer(qs, many=False)
            headers = self.get_success_headers(serializer.data)
            return Response(serializer.data, status=200, headers=headers)

# 入库批次类视图
class BoundBatchViewSet(viewsets.ModelViewSet):
    """
        retrieve:
            Response a data list(get)
            list:
            Response a data list(all)
            create:
            Create a data line(post)
        delete:
            Delete a data line(delete)
            """
    # authentication_classes = []  # 禁用所有认证类
    # permission_classes = [AllowAny]  # 允许任意访问
    pagination_class = MyPageNumberPagination
    filter_backends = [DjangoFilterBackend, OrderingFilter, ]
    ordering_fields = ['id', "create_time", "update_time", ]
    filter_class = BoundBatchFilter

    def get_project(self):
        try:
            id = self.kwargs.get('pk')
            return id
        except:
            return None

    def get_queryset(self):
        id = self.get_project()
        if self.request.user:
            if id is None:
                return BoundBatchModel.objects.filter( is_delete=False)
            else:
                return BoundBatchModel.objects.filter( id=id, is_delete=False)
        else:
            return BoundBatchModel.objects.none()

    def get_serializer_class(self):
        if self.action in ['list', 'destroy','retrieve']:
            return BoundBatchGetSerializer
        elif self.action in ['create', 'update']:
            return BoundBatchPostSerializer
        else:
            return self.http_method_not_allowed(request=self.request)

    def create(self, request, *args, **kwargs):
        data = self.request.data
        try:
            data['openid'] = self.request.auth.openid
            data['goods_total_weight'] = data['goods_weight']*data['goods_qty']
        
            order_day=str(timezone.now().strftime('-%Y%m'))
            order_month=str(timezone.now().strftime('%Y%m'))
            data['bound_month'] =str(timezone.now().strftime('%Y%m'))
            print(data['order'])
            if data['order'] == 'true':
                qs_set = BoundBatchModel.objects.filter( goods_code=data['goods_code'], bound_month=order_month,  is_delete=False)
                print('qs_set是:', len(qs_set))
                if len(qs_set) > 0:
                    bound_last_code = qs_set.order_by('-bound_batch_order').first().bound_number
                    data['bound_batch_order'] = int(bound_last_code.split('-')[-1])+1
                    data['bound_number'] = data['goods_code'] + '-' + str(int(bound_last_code.split('-')[-1])+1)
                else:
                    data['bound_batch_order'] = int(order_day.split('-')[-1])*1000 +1
                    data['bound_number'] = data['goods_code'] + order_day + '001'
            else:
                data['bound_number'] = data['goods_code'] + '-' + str(data['bound_batch_order'])
            serializer = self.get_serializer(data=data)
            serializer.is_valid(raise_exception=True)
            serializer.save()
            headers = self.get_success_headers(serializer.data)
            self.add_batch_log(serializer.data, 0, data['goods_qty'])

            return Response(serializer.data, status=200, headers=headers)
        except Exception as e:
            print(e)
            raise APIException({"detail": "{}".format(e)})
    
    def add_batch_log(self, data, log_type, goods_qty):
        choices_dict = dict(BatchLogModel.BATCH_LOG_TYPE)
        log_type_name = choices_dict.get(log_type, "未知类型")
        
        try:
            # 获取 BoundBatchModel 实例
            batch_obj = BoundBatchModel.objects.get(id=data['id'])
        except BoundBatchModel.DoesNotExist:

            return False

        log_data = {
            'batch_id': batch_obj,  
            'log_type': log_type,
            'log_date': timezone.now().strftime('%Y-%m-%d-%H:%M'),  # 直接格式化时间,无需转字符串
            'goods_code': data['goods_code'],
            'goods_desc': data['goods_desc'],
            'goods_qty': data['goods_qty'],
            'log_content': f"{log_type_name} {data['goods_qty']}件",
            'creater': data['creater'],
            'openid': data['openid'],
            'is_delete': False,
            
        }
        
        # 创建日志记录
        BatchLogModel.objects.create(**log_data)
        return True


    def update(self, request, pk):
        qs = self.get_object()
        data = self.request.data
        serializer = self.get_serializer(qs, data=data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=200, headers=headers)

    def destroy(self, request, pk):
        qs = self.get_object()
        if qs.openid != self.request.auth.openid:
            raise APIException({"detail": "该入库非您所属,禁止删除,您可以进行编辑"})
        else:
            qs.is_delete = True
            qs.save()
            serializer = self.get_serializer(qs, many=False)
            headers = self.get_success_headers(serializer.data)
            return Response(serializer.data, status=200, headers=headers)

# 入库明细类视图      
class BoundDetailViewSet(viewsets.ModelViewSet):
    """
        retrieve:
            Response a data list(get)
            list:
            Response a data list(all)
        create:
            Create a data line(post)
        delete:
            Delete a data line(delete)
            """
    # authentication_classes = []  # 禁用所有认证类
    # permission_classes = [AllowAny]  # 允许任意访问
    pagination_class = MyPageNumberPagination
    filter_backends = [DjangoFilterBackend, OrderingFilter, ]
    ordering_fields = ['id', "create_time", "update_time", ]
    filter_class = BoundDetailFilter

    def get_project(self):
        try:
            id = self.kwargs.get('pk')
            return id
        except:
            return None
            
    def get_queryset(self):
        id = self.get_project()
        if self.request.user:
            if id is None:
                return BoundDetailModel.objects.filter( is_delete=False)
            else:
                return BoundDetailModel.objects.filter( id=id, is_delete=False)
        else:
            return BoundDetailModel.objects.none()

    def get_serializer_class(self):
        if self.action in ['list', 'destroy','retrieve']:
            return BoundDetailGetSerializer
        elif self.action in ['create', 'update']:
            return BoundDetailPostSerializer
        else:
            return self.http_method_not_allowed(request=self.request)


    def create(self, request, *args, **kwargs):
        data = self.request.data
        data['openid'] = self.request.auth.openid
        data.setdefault('is_delete', False)


        # 验证并保存数据
        data['detail_code'] = f"DC-{data['bound_list']:02}{data['bound_batch']:02}"
        print(data['detail_code'])
        if BoundDetailModel.objects.filter(detail_code=data['detail_code'], is_delete=False).exists():
            raise APIException({"detail": "Data exists"})
        else:
            serializer = self.get_serializer(data=data)
            serializer.is_valid(raise_exception=True)
            serializer.save()

            # 返回响应
            headers = self.get_success_headers(serializer.data)
            return Response(serializer.data, status=200, headers=headers)
    
    def update(self, request, pk):
        qs = self.get_object()
        data = self.request.data
        serializer = self.get_serializer(qs, data=data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=200, headers=headers)

    def destroy(self, request, pk):
        qs = self.get_object()
        if qs.openid != self.request.auth.openid:
            raise APIException({"detail": "该入库非您所属,禁止删除,您可以进行编辑"})
        else:
            qs.is_delete = True
            qs.save()
            serializer = self.get_serializer(qs, many=False)
            headers = self.get_success_headers(serializer.data)
            return Response(serializer.data, status=200, headers=headers)

# 出库明细类视图      
class OutBoundDetailViewSet(viewsets.ModelViewSet):
    """
        retrieve:
            Response a data list(get)
            list: Response a data list(all)
        create:
            Create a data line(post)
        delete:
            Delete a data line(delete)
    """
    # authentication_classes = []  # 禁用所有认证类
    # permission_classes = [AllowAny]  # 允许任意访问
    pagination_class = MyPageNumberPagination
    filter_backends = [DjangoFilterBackend, OrderingFilter, ]
    ordering_fields = ['id', "create_time", "update_time", ]
    filter_class = OutBoundDetailFilter

    def get_project(self):
        try:
            id = self.kwargs.get('pk')
            return id
        except:
            return None            

    def get_queryset(self):
        id = self.get_project()
        if self.request.user:            
            if id is None:
                return OutBoundDetailModel.objects.filter( is_delete=False)
            else:
                return OutBoundDetailModel.objects.filter( id=id, is_delete=False)
        else:
            return OutBoundDetailModel.objects.none()

    def get_serializer_class(self):
        if self.action in ['list', 'destroy','retrieve']:
            return OutBoundDetailGetSerializer
        elif self.action in ['create', 'update']:
            return OutBoundDetailPostSerializer
        else:
            return self.http_method_not_allowed(request=self.request)

    def create(self, request, *args, **kwargs):
        data = self.request.data
        data['openid'] = self.request.auth.openid
        data.setdefault('is_delete', False)

        data['bound_batch_number'] = OutBatchModel.objects.get(id=data['bound_batch']).batch_number.id
        # 验证并保存数据
        data['detail_code'] = f"DC-{data['bound_list']:02}{data['bound_batch']:02}"
        print(data['detail_code'])
        if OutBoundDetailModel.objects.filter(detail_code=data['detail_code'], is_delete=False).exists():
            raise APIException({"detail": "Data exists"})
        else:
            serializer = self.get_serializer(data=data)
            serializer.is_valid(raise_exception=True)
            serializer.save()

            # 返回响应
            headers = self.get_success_headers(serializer.data)
            return Response(serializer.data, status=200, headers=headers)

    def update(self, request, pk):
        qs = self.get_object()
        data = self.request.data
        serializer = self.get_serializer(qs, data=data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=200, headers=headers)

    def destroy(self, request, pk):
        qs = self.get_object()
        if qs.openid != self.request.auth.openid:
            raise APIException({"detail": "该入库非您所属,禁止删除,您可以进行编辑"})
        else:
            qs.is_delete = True
            qs.save()
            serializer = self.get_serializer(qs, many=False)
            headers = self.get_success_headers(serializer.data)
            return Response(serializer.data, status=200, headers=headers)       

# 出库批次类视图      
class OutBoundBatchViewSet(viewsets.ModelViewSet):
    """
        retrieve:
            Response a data list(get)
            list:
            Response a data list(all)
            create:
            Create a data line(post)
        delete:
            Delete a data line(delete)
            """
    # authentication_classes = []  # 禁用所有认证类
    # permission_classes = [AllowAny]  # 允许任意访问
    pagination_class = MyPageNumberPagination
    filter_backends = [DjangoFilterBackend, OrderingFilter, ]
    ordering_fields = ['id', "create_time", "update_time", ]
    filter_class = OutBatchFilter

    def get_project(self):
        try:
            id = self.kwargs.get('pk')
            return id
        except:
            return None

    def get_queryset(self):
        id = self.get_project()
        if self.request.user:
            if id is None:                
                return OutBatchModel.objects.filter( is_delete=False)
            else:
                return OutBatchModel.objects.filter( id=id, is_delete=False)
        else:
            return OutBatchModel.objects.none()

    def get_serializer_class(self):
        if self.action in ['list', 'destroy','retrieve']:
            return OutBatchGetSerializer
        elif self.action in ['create', 'update']:
            return OutBatchPostSerializer
        else:
            return self.http_method_not_allowed(request=self.request)

    def create(self, request, *args, **kwargs):
        data = self.request.data
        batch_obj = BoundBatchModel.objects.get(bound_number=data['out_number'])
        if batch_obj is None:
            raise APIException({"detail": "批次不存在"})

        bound_obj = BoundListModel.objects.get(id=data['bound_list_id'])
        data['bound_list'] = bound_obj.id
        data['batch_number'] = batch_obj.id
        data['out_date'] = str(timezone.now().strftime('%Y-%m-%d %H:%M:%S'))

        data['openid'] = self.request.auth.openid
        data.setdefault('is_delete', False)
        data['goods_total_weight'] = data['goods_weight']*data['goods_out_qty']
        data['goods_qty'] = batch_obj.goods_qty -batch_obj.goods_reserve_qty - data['goods_out_qty']

        data['status'] = 0  #现在处于出库申请状态
   
        serializer = self.get_serializer(data=data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        headers = self.get_success_headers(serializer.data)
        self.add_batch_log(serializer.data, 1, data['goods_out_qty'])
        
        return Response(serializer.data, status=200, headers=headers)

    def update(self, request, pk):        
        qs = self.get_object()
        data = self.request.data
        data['openid'] = self.request.auth.openid
        data.setdefault('is_delete', False)
        data['goods_total_weight'] = data['goods_weight']*data['goods_qty']
        serializer = self.get_serializer(qs, data=data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        headers = self.get_success_headers(serializer.data)
        self.add_batch_log(serializer.data, 1, data['goods_qty'])
        return Response(serializer.data, status=200, headers=headers)

    def destroy(self, request, pk):
        qs = self.get_object()
        if qs.openid != self.request.auth.openid:            
            raise APIException({"detail": "该出库非您所属,禁止删除,您可以进行编辑"})
        else:
            qs.is_delete = True
            qs.save()
            serializer = self.get_serializer(qs, many=False)
            headers = self.get_success_headers(serializer.data)
            return Response(serializer.data, status=200, headers=headers)

    def add_batch_log(self, data, log_type, goods_qty):
        choices_dict = dict(BatchLogModel.BATCH_LOG_TYPE)
        log_type_name = choices_dict.get(log_type, "未知类型")

        try:
            # 获取 BoundBatchModel 实例
            batch_obj = BoundBatchModel.objects.get(id=data['batch_number'])
        except BoundBatchModel.DoesNotExist:
            # 处理批次不存在的情况(如记录日志或抛出异常)
            return False

        log_data = {            
            'batch_id': batch_obj,  # 关键修复:传入实例对象,而不是 batch_obj.id
            'log_type': log_type,
            'log_date': timezone.now().strftime('%Y-%m-%d-%H:%M'),  # 直接格式化时间,无需转字符串
            'goods_code': data['goods_code'],
            'goods_desc': data['goods_desc'],
            'goods_qty': data['goods_qty'],
            'log_content': f"{log_type_name} {goods_qty}件",
            'creater': data['creater'],
            'openid': data['openid'],
            'is_delete': False,
            # 注意:create_time 和 update_time 由模型的 auto_now_add 和 auto_now 自动处理,无需手动赋值
        }

        # 创建日志记录
        BatchLogModel.objects.create(**log_data)
        return True 

# 批次操作日志类视图      
class BoundBatchLogViewSet(viewsets.ModelViewSet):
    
    """
        retrieve:
            Response a data list(get)
            list:
            Response a data list(all)
     
            delete:
            Delete a data line(delete)
    """ 
    # authentication_classes = []  # 禁用所有认证类
    # permission_classes = [AllowAny]  # 允许任意访问
    pagination_class = MyPageNumberPagination
    filter_backends = [DjangoFilterBackend, OrderingFilter, ]
    ordering_fields = ['id', "create_time", "update_time", ]
    filter_class = BatchlogFilter

    def get_queryset(self):

        return BatchLogModel.objects.filter( is_delete=False)
        

    def get_serializer_class(self):
        if self.action in ['list', 'destroy','retrieve']:
            return BatchLogGetSerializer
        else:
            return self.http_method_not_allowed(request=self.request)

    def destroy(self, request, pk):
        qs = self.get_object()
        qs.is_delete = True
        qs.save()
        serializer = self.get_serializer(qs, many=False)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=200, headers=headers)  

# 托盘类视图      
class BatchContainerAPIView(APIView):
    """
        post:
            返回批次对应的container列表
    """
    # authentication_classes = []  # 禁用所有认证类
    # permission_classes = [AllowAny]  # 允许任意访问
    def post(self, request):
        data = request.data
        batch_id = data.get('batch_id')
        from container.models import ContainerDetailModel


        container_detail_all = ContainerDetailModel.objects.filter(batch_id=batch_id, is_delete=False).exclude(status=3).all()
        container_dict = {}

        for container_detail in container_detail_all:
            container_id = container_detail.container_id

            if container_id not in container_dict:
                container_dict[container_id] = {
                    'id': container_id,
                    'goods_code': container_detail.goods_code,
                    'goods_desc': container_detail.goods_desc,
             
                    'container_code': container_detail.container.container_code,
                    'current_location': container_detail.container.current_location,
                    'goods_qty': container_detail.goods_qty-container_detail.goods_out_qty,
                    'class':container_detail.goods_class
                }
            else:
                container_dict[container_id]['goods_qty'] += container_detail.goods_qty-container_detail.goods_out_qty
        container_dict = list(container_dict.values())
        return_data = {'code': 200,'msg': 'Success Create', 'data': container_dict}
        return Response(return_data)