from django.db import transaction
from rest_framework.response import Response
from rest_framework.views import APIView
from django.utils import timezone
from .models import ContainerListModel,ContainerDetailModel,ContainerOperationModel,TaskModel,ContainerWCSModel
from bound.models import BoundBatchModel,BoundDetailModel,BoundListModel
from .serializers import *

class ContainerService:
    """
    托盘管理服务
        function:
            create_container_operation: 创建托盘操作记录

    """
    @staticmethod
    @transaction.atomic
    def create_container_operation(data, logger):
     
        # 初始化基础数据
        data['month'] = timezone.now().strftime('%Y%m')
        
        # 处理托盘
        container = ContainerManager.get_or_create_container(
            container_code=data.get('container'),
            logger=logger
        )
        data['container_code'] = container.container_code

        data['container'] = container.id

        # 处理批次数据
        if data.get('goods_class') == 2:
            return BatchProcessor.handle_special_batches(data, logger)
        return BatchProcessor.handle_normal_batches(data, logger)

class ContainerManager:
    @staticmethod
    def get_or_create_container(container_code, logger):
        """统一管理托盘对象"""
        if container := ContainerListModel.objects.filter(container_code=container_code).first():
            logger.info(f"托盘 {container_code} 已存在")
            return container
            
        logger.info(f"创建新托盘 {container_code}")
        serializer = ContainerListPostSerializer(data={'container_code': container_code})
        serializer.status = 5
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return ContainerListModel.objects.filter(container_code=container_code).first()

class BatchProcessor:
    @staticmethod
    def handle_normal_batches(data, logger):
        """标准批次处理流程"""
        for batch in data.get('batches', []):
            try:
                BatchOperator.process_single_batch(data, batch, logger)
            except Exception as e:
                logger.error(f"批次处理失败: {str(e)}")
                continue
        from bin.queries import LocationQueries
        LocationQueries.get_batch_info(data.get('container_code'))
        return Response({"status": "success"})

    @staticmethod
    def handle_special_batches(data, logger):
        """托盘组处理流程"""
        for batch in data.get('batches', []):
            try:
                BatchOperator.process_single_container(data, batch, logger)
            except Exception as e:
                logger.error(f"托盘组处理失败: {str(e)}")
                continue
        return Response({"status": "success"})

class BatchOperator:
    @staticmethod
    def process_single_container(data, batch, logger):
        """单个批次处理托盘"""
        # 获取批次对象
        container_obj = ContainerManager.get_or_create_container(
            batch.get('goods_code'), 
            logger
        )

        # 更新批次状态
        update_result = BatchStatusUpdater.update_container_status(
            container_obj, 
            5,
            data.get('container_code'),
        )
        print(update_result)
        # 创建托盘关联记录

        RecordCreator.create_container_related_records(
            data=data,
            container_obj=container_obj
        )

    @staticmethod
    def process_single_batch(data, batch, logger):
        """单个批次处理批次"""
        # 获取批次对象
        bound_obj = BatchValidator.get_valid_batch(
            batch.get('goods_code'), 
            logger
        )
        
        # 更新批次状态(新增数目)
        update_result = BatchStatusUpdater.update_status(
            bound_obj, 
            batch['goods_qty'] * batch['goods_group'],
            logger
        )
        
        # 创建关联记录
        RecordCreator.create_related_records(
            data=data,
            bound_obj=bound_obj,
            batch_data= batch,
            qty_diff=update_result['added_qty'],
            logger=logger
        )

class BatchValidator:
    @staticmethod
    def get_valid_batch(bound_number, logger):
        """批次校验模块"""
        if not (bound_obj := BoundBatchModel.objects.filter(bound_number=bound_number).first()):
            logger.error(f"批次 {bound_number} 不存在")
            raise ValueError("无效批次号")
        return bound_obj

class BatchStatusUpdater:
    @staticmethod
    def update_status(bound_obj, added_qty, logger):
        """批次状态管理"""
        last_qty = bound_obj.goods_in_qty
        bound_obj.goods_in_qty += added_qty
        
        if bound_obj.goods_in_qty >= bound_obj.goods_qty:
            FullBatchHandler.mark_as_completed(bound_obj, logger)
        else:
            bound_obj.status = 0
        
        bound_obj.save()
        return {
            'last_qty': last_qty,
            'added_qty': added_qty
        }
    @staticmethod
    def update_container_status(container_obj, status, container_code):
        """批次状态管理""" 
    
        container_obj.status = status
        container_obj.available = False
        container_obj.current_location = '托盘'+str(container_code)
        container_obj.save()
        return {
            'last_qty': 1,
            'added_qty': 1
        }
  

class FullBatchHandler:
    @staticmethod
    def mark_as_completed(bound_obj, logger):
        """满批次处理"""
        # bound_obj.goods_in_qty = bound_obj.goods_qty
        bound_obj.status = 1
        BatchRelationUpdater.update_related_records(bound_obj, logger)

class BatchRelationUpdater:
    @staticmethod
    def update_related_records(bound_obj, logger):
        """更新关联单据"""
        if detail := BoundDetailModel.objects.filter(bound_batch=bound_obj.id).first():
            detail.status = 1
            detail.save()
            CompletionChecker.check_list_completion(detail.bound_list_id, logger)

class CompletionChecker:
    @staticmethod
    def check_list_completion(list_id, logger):
        """完成度检查"""
        completed = BoundDetailModel.objects.filter(bound_list=list_id, status=1).count()
        total = BoundDetailModel.objects.filter(bound_list=list_id).count()
        
        if completed == total:
            ListStatusUpdater.update_list_status(list_id, 102, logger)

class ListStatusUpdater:
    @staticmethod
    def update_list_status(list_id, status, logger):
        """更新单据状态"""
        if list_obj := BoundListModel.objects.filter(id=list_id).first():
            list_obj.bound_status = status
            list_obj.save()
            logger.info("入库申请全部完成")

class RecordCreator:
    @staticmethod
    def create_container_related_records(data, container_obj, qty_diff=1):
        """记录创建批次"""
        # 生成明细记录
        detail_data = RecordBuilder.build_detail_data_container_group(
            data=data,
            container_obj=container_obj,
            qty_diff=qty_diff
        )

        DetailRecordCreator.create_container_related_records(detail_data)
        
        # 生成操作记录
        operation_data = RecordBuilder.build_operation_data_container_group(
            detail_data=detail_data,
            qty_diff=qty_diff
        )

        OperationRecordCreator.create_container_related_operation_records(operation_data)

    @staticmethod
    def create_related_records(data, bound_obj, batch_data, qty_diff, logger):
        """记录创建批次"""
        # 生成明细记录

        goods_group = batch_data.get('goods_group')
        goods_qty = batch_data.get('goods_qty')
        for i in range(goods_group):
            detail_data = RecordBuilder.build_detail_data(
                data=data,
                bound_obj=bound_obj,
                qty_diff=goods_qty
            )
            DetailRecordCreator.create_record(detail_data)
        
        # 生成操作记录
        operation_data = RecordBuilder.build_operation_data(
            detail_data=detail_data,
            qty_diff=qty_diff
        )
        OperationRecordCreator.create_operation_record(operation_data)



class RecordBuilder:
    @staticmethod
    def build_detail_data(data, bound_obj, qty_diff):
        """构建明细数据结构"""
        return {
            "container": data['container'],
            "batch": bound_obj.id,
            "goods_code": bound_obj.goods_code,
            "goods_desc": bound_obj.goods_desc,
            "goods_qty": qty_diff,
            "goods_weight": bound_obj.goods_weight,
            "status": 1,
            "month": data['month'],
            "creater": data.get('creater', 'wms')
        }
    
    @staticmethod
    def build_detail_data_container_group(data, container_obj, qty_diff=1):
        """构建明细数据结构"""
        return {
            "container": data['container'],
            "goods_code": container_obj.container_code,
            "goods_desc": '托盘组',
            "goods_qty": qty_diff,
            "goods_weight": 0,
            "status": 1,
            "month": data['month'],
            "creater": data.get('creater', 'wms')
        }

    @staticmethod
    def build_operation_data(detail_data, qty_diff):
        """构建操作记录数据"""

        return {
            "month": detail_data['month'],
            "container": detail_data['container'],
            "operation_type": 'container',
            "batch": detail_data['batch'],
            "goods_code": detail_data['goods_code'],
            "goods_desc": detail_data['goods_desc'],
            "goods_qty": qty_diff,
            "goods_weight": qty_diff,
            "operator": detail_data['creater'],
            "timestamp": timezone.now(),
            "from_location": "container",
            "to_location": "container",
            "memo": f"每组{detail_data['goods_code']}数目{detail_data['goods_qty']},PDA组盘共计组盘{qty_diff}"
        }
    
    def build_operation_data_container_group(detail_data, qty_diff):
        """构建操作记录数据"""

        return {
            "month": detail_data['month'],
            "container": detail_data['container'],
            "operation_type": 'container',
            "goods_code": detail_data['goods_code'],
            "goods_desc": detail_data['goods_desc'],
            "goods_qty": qty_diff,
            "goods_weight": detail_data['goods_weight'],
            "operator": detail_data['creater'],
            "timestamp": timezone.now(),
            "from_location": "container",
            "to_location": "container",
            "memo": f"托盘组下的:{detail_data['goods_code']}合盘"
        }

class DetailRecordCreator:
    @staticmethod
    def create_record(data):
        """统一创建明细记录"""
        serializer = ContainerDetailPostSerializer(data=data)
        serializer.is_valid(raise_exception=True)
        serializer.save()

    def create_container_related_records(data):
        """记录创建批次"""
        # 生成明细记录
        container_obj = ContainerListModel.objects.filter(id=data['container']).first()
        container_obj.status = 5
        container_obj.save()
        if ContainerDetailModel.objects.filter(container=container_obj,goods_code=data['goods_code'],status=1,is_delete=False).first():
            return 
        ContainerDetailModel.objects.create(
            container=container_obj,
            goods_code=data['goods_code'],
            goods_desc=data['goods_desc'],
            goods_qty=data['goods_qty'],
            goods_weight=data['goods_weight'],
            goods_class=2,
            status=data['status'],
            month=data['month'],
            creater=data['creater']
        )

class OperationRecordCreator:
    @staticmethod
    def create_operation_record(data):
        """统一创建操作记录"""
        serializer = ContainerOperationPostSerializer(data=data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
    @staticmethod

    def create_container_related_operation_records(data):
        container_obj = ContainerListModel.objects.filter(id=data['container']).first()

        if ContainerOperationModel.objects.filter(container_id=container_obj.id,goods_code=data['goods_code'],is_delete=False).first():
            return 
        ContainerOperationModel.objects.create(      
            month=data['month'],
            container_id=container_obj.id,
            operation_type=data['operation_type'],
            bound_id=None,
            goods_code=data['goods_code'],
            goods_desc=data['goods_desc'],
            goods_qty=data['goods_qty'],
            goods_weight=data['goods_weight'],
            operator=data['operator'],
            timestamp=data['timestamp'],
            from_location=data['from_location'],
            to_location=data['to_location'],
            memo=data['memo']
        )

# 最终视图类
class OperationView(APIView):
    def create(self, request, *args, **kwargs):
        try:
            return ContainerService.create_container_operation(
                data=request.data,
                logger=self.get_logger()  # 假设有日志方法
            )
        except Exception as e:
            return Response({"error": str(e)}, status=400)