from django.db import models
from bound.models import BoundBatchModel,BoundDetailModel,OutBatchModel,BoundListModel,BoundListModel
from django.utils import timezone
from django.db.models.signals import pre_save, post_save
from django.dispatch import receiver

# Create your models here.
# 主表:托盘数据
class ContainerListModel(models.Model):
    CONTAINER_STATUS = (
        (0, '空置'),
        (1, '入库中'),
        (2, '在库'),
        (3, '出库中'),
        (4, '已出库'),
        (5, '空托盘组')
    )
   
    container_code = models.IntegerField( verbose_name='托盘编号',unique=True)
    current_location = models.CharField(max_length=50, verbose_name='当前库位', default='N/A')
    target_location = models.CharField(max_length=50, verbose_name='目标库位', default='N/A')
    available= models.BooleanField(default=True, verbose_name='可用')
    status = models.IntegerField(choices=CONTAINER_STATUS, default=0, verbose_name='托盘状态')
    last_operation = models.DateTimeField(auto_now=True, verbose_name='最后操作时间')

    class Meta:
        db_table = 'container_list'
        verbose_name = 'ContainerList'
        verbose_name_plural = "ContainerList"
        ordering = ['-container_code']

class ContainerDetailModel(models.Model):
    BATCH_STATUS=(
        (0, '空盘'),
        (1, '组盘'),
        (2, '在库'),
        (3, '已出库')
    )
    BATCH_CLASS = (
        (1, '成品'),
        (2, '空盘'),
        (3, '散盘'),
    )
    
    month = models.IntegerField(verbose_name='月份')
    container = models.ForeignKey(ContainerListModel, on_delete=models.CASCADE, related_name='details')
    batch = models.ForeignKey(BoundBatchModel, on_delete=models.CASCADE, verbose_name='批次',blank=True, null=True)
    goods_class = models.IntegerField(verbose_name='货品类别',choices=BATCH_CLASS, default=1)
    goods_code = models.CharField(max_length=50, verbose_name='货品编码')
    goods_desc = models.CharField(max_length=100, verbose_name='货品描述')
    goods_qty = models.IntegerField(verbose_name='数量')
    goods_out_qty = models.IntegerField(verbose_name='出库数量', default=0)
    goods_weight = models.DecimalField(max_digits=10, decimal_places=3, verbose_name='重量')
    status = models.IntegerField(choices=BATCH_STATUS,default=0, verbose_name='状态')          
    creater = models.CharField(max_length=50, verbose_name='创建人')
    create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
    is_delete = models.BooleanField(default=False, verbose_name='是否删除')

    class Meta:
        db_table = 'container_detail'
        verbose_name = 'ContainerDetail'
        verbose_name_plural = "ContainerDetail"
        ordering = ['-id']
        indexes = [
            models.Index(fields=['container']),
            models.Index(fields=['batch']),
            models.Index(fields=['goods_code']),
            models.Index(fields=['status']),
        ]

    def __str__(self):
        return f"{self.container.container_code} - {self.batch.bound_number if self.batch else 'N/A'} - {self.goods_code}"
    
    def save(self, *args, **kwargs):
        """
        更新托盘上的物料数量,更新批次上的
        goods_in_qty(组盘数目)
        ,goods_in_location_qty(在库数目)
        ,goods_out_qty(出库数目)
        """
        # 在保存前调用信号处理器
        if self.pk:
            # 获取状态变化前的状态
            original = ContainerDetailModel.objects.get(pk=self.pk)
            original_status = original.status
            
        super().save(*args, **kwargs)
        
        # 更新批次数据
        if self.batch:
            # 避免循环更新 - 仅在数量相关字段变更时才更新
            if 'update_fields' not in kwargs or any(field in kwargs['update_fields'] for field in ['goods_qty', 'goods_out_qty','is_delete']):
                self.update_batch_stats()
            
            # # 根据出库数量更新状态
            # if self.goods_out_qty > self.goods_qty:
            #     # 出库数量不能大于总数量
            #     self.goods_out_qty = self.goods_qty
            #     self.save(update_fields=['goods_out_qty'])
                
            # 根据当前数量状态更新状态
            if self.goods_out_qty >= self.goods_qty:
                self.status = 3  # 已出库
                super().save(*args, **kwargs)
                
            elif self.goods_qty - self.goods_out_qty > 0 and self.goods_out_qty > 0:
                self.status = 2  # 在库
                super().save(*args, **kwargs)

              
            if self.status == 3 and self.goods_qty - self.goods_out_qty > 0 :
                self.status = 2  # 在库
                super().save(*args, **kwargs)


             # 更新货物分类(关键修改点)
            if not kwargs.get('skip_class_update', False):
                # 获取托盘上所有物料(排除已删除和已出库的)
                details = ContainerDetailModel.objects.filter(
                    container=self.container.id,
                    is_delete=False
                ).exclude(status=3)
                
                # 统计不同批次数目
                batch_count = details.values('batch').distinct().count()
                new_class = 1 if batch_count == 1 else 3
                
                # 批量更新所有相关物料的goods_class
                details.exclude(goods_class=new_class).update(goods_class=new_class)
                
                # 如果当前物料的class需要更新
           
                if self.goods_class != new_class:
                    self.goods_class = new_class
                    super().save(update_fields=['goods_class'])
    
    def update_batch_stats(self):
        """更新批次的统计数据"""
        if not self.batch:
            return
            
        # 聚合托盘明细数据
        stats = ContainerDetailModel.objects.filter(
            batch=self.batch,
            is_delete=False
        ).aggregate(
            total_qty=models.Sum('goods_qty'),
            total_out_qty=models.Sum('goods_out_qty')
        )
        
        # 更新批次数据
        self.batch.goods_in_qty = stats['total_qty'] or 0
        self.batch.goods_in_location_qty = (stats['total_qty'] or 0) - (stats['total_out_qty'] or 0)
        self.batch.goods_out_qty = stats['total_out_qty'] or 0
        self.batch.save()
        





class ContainerDetailLogModel(models.Model):
    """托盘明细变更日志模型"""
    LOG_TYPES = (
        ('create', '创建'),
        ('update', '更新'),
        ('delete', '删除'),
        ('out', '出库'),
        ('status_change', '状态变更'),
    )
    
    # 关联的托盘明细
    container_detail = models.ForeignKey(
        ContainerDetailModel, 
        on_delete=models.CASCADE,
        related_name='logs'
    )
    
    # 日志类型
    log_type = models.CharField(
        max_length=20,
        choices=LOG_TYPES,
        verbose_name='日志类型'
    )
    
    # 原值
    old_goods_qty = models.IntegerField(verbose_name='原数量', null=True, blank=True)
    old_goods_out_qty = models.IntegerField(verbose_name='原出库数量', null=True, blank=True)
    old_status = models.IntegerField(
        choices=ContainerDetailModel.BATCH_STATUS,
        null=True,
        blank=True,
        verbose_name='原状态'
    )
    
    # 新值
    new_goods_qty = models.IntegerField(verbose_name='新数量', null=True, blank=True)
    new_goods_out_qty = models.IntegerField(verbose_name='新出库数量', null=True, blank=True)
    new_status = models.IntegerField(
        choices=ContainerDetailModel.BATCH_STATUS,
        null=True,
        blank=True,
        verbose_name='新状态'
    )
    
    # 元信息
    creater = models.CharField(max_length=50, verbose_name='操作人')
    create_time = models.DateTimeField(auto_now_add=True, verbose_name='操作时间')
    
    class Meta:
        db_table = 'container_detail_log'
        verbose_name = '托盘明细变更日志'
        verbose_name_plural = "托盘明细变更日志"
        ordering = ['-create_time']
    
    def __str__(self):
        return f"{self.container_detail} - {self.get_log_type_display()} - {self.create_time.strftime('%Y-%m-%d %H:%M:%S')}"  



@receiver(pre_save, sender=ContainerDetailModel)
def container_detail_pre_save(sender, instance, **kwargs):
    """在托盘明细保存前记录变更"""
    # 检查是否是新建对象
    if instance.pk:
        try:
            # 获取数据库中的当前对象
            old_instance = ContainerDetailModel.objects.get(pk=instance.pk)
        except ContainerDetailModel.DoesNotExist:
            return
            
        # 创建日志记录
        log = ContainerDetailLogModel(container_detail=instance, creater=instance.creater)
        
        # 检查数量变化
        if old_instance.goods_qty != instance.goods_qty:
            log.old_goods_qty = old_instance.goods_qty
            log.new_goods_qty = instance.goods_qty
            log.log_type = 'update'
            log.save()
            
        # 检查出库数量变化
        if old_instance.goods_out_qty != instance.goods_out_qty:
            log.old_goods_out_qty = old_instance.goods_out_qty
            log.new_goods_out_qty = instance.goods_out_qty
            log.log_type = 'out'
            log.save()

            
        # # 检查状态变化
        # if old_instance.status != instance.status:
        #     log.old_status = old_instance.status
        #     log.new_status = instance.status
        #     log.log_type = 'status_change'
            
        # # 保存日志记录
        # if hasattr(log, 'log_type'):
        #     log.save()

@receiver(post_save, sender=ContainerDetailModel)
def container_detail_post_save(sender, instance, created, **kwargs):
    """在托盘明细保存后记录创建"""
    if created:
        # 为新建的对象创建日志
        ContainerDetailLogModel.objects.create(
            container_detail=instance,
            log_type='create',
            creater=instance.creater,
            new_goods_qty=instance.goods_qty,
            new_status=instance.status
        )

    


# 明细表:操作记录 记录每次出入库的记录,使用goods来进行盘点,使用托盘码来进行托盘的操作记录
class ContainerOperationModel(models.Model):
    OPERATION_TYPES = (
        ('container','组盘'),
        ('inbound', '入库'),
        ('outbound', '出库'), 
        ('adjust', '调整'),
    )
    month = models.IntegerField(verbose_name='月份')
    container = models.ForeignKey(ContainerListModel, on_delete=models.CASCADE, related_name='operations')
    operation_type = models.CharField(max_length=20, choices=OPERATION_TYPES, verbose_name='操作类型')
    bound_id = models.IntegerField(verbose_name='出库申请', null=True, blank=True)

    batch = models.ForeignKey(BoundBatchModel, on_delete=models.CASCADE, verbose_name='批次',null=True, blank=True)
    goods_code = models.CharField(max_length=50, verbose_name='货品编码')
    goods_desc = models.CharField(max_length=100, verbose_name='货品描述')
    goods_qty = models.IntegerField(verbose_name='数量')
    goods_weight = models.DecimalField(max_digits=10, decimal_places=3, verbose_name='重量')

    operator = models.CharField(max_length=50, verbose_name='操作人')
    timestamp = models.DateTimeField(auto_now_add=True, verbose_name='操作时间')    
    from_location = models.CharField(max_length=50, null=True, verbose_name='原库位')
    to_location = models.CharField(max_length=50, null=True, verbose_name='目标库位')
    memo = models.TextField(null=True, verbose_name='备注')
    is_delete = models.BooleanField(default=False, verbose_name='是否删除')


    class Meta:
        db_table = 'container_operation'    
        verbose_name = 'ContainerOperation'
        verbose_name_plural = "ContainerOperation"
        ordering = ['-timestamp']

class ContainerWCSModel(models.Model):
    TASK_STATUS = (
        (100, '等待中'),
        (101, '处理中'),
        (102, '已暂停'),
        (103, '入库中'),
        (200, '已发送'),
        (300, '已完成'),
        (400, '失败'),
    )
    taskid = models.CharField(max_length=50, verbose_name='任务ID')
    batch = models.ForeignKey(BoundBatchModel, on_delete=models.CASCADE, verbose_name='关联批次',null=True, blank=True )
    batch_out = models.ForeignKey(OutBatchModel, on_delete=models.CASCADE, verbose_name='出库批次' , null=True, blank=True )
    bound_list = models.ForeignKey(BoundListModel, on_delete=models.CASCADE, verbose_name='关联出库单',null=True, blank=True )
    batch_number = models.CharField(max_length=50, verbose_name='批次号',null=True, blank=True )
    sequence = models.BigIntegerField(verbose_name='任务顺序')
    priority = models.IntegerField(default=100, verbose_name='优先级')
    month = models.IntegerField(verbose_name='月份')
    tasktype = models.CharField(max_length=50, verbose_name='任务类型')
    tasknumber = models.IntegerField(verbose_name='任务号',unique=True)
    order_number = models.IntegerField(verbose_name='c_number')
    container = models.CharField(max_length=50, verbose_name='托盘号')
    current_location = models.CharField(max_length=50, verbose_name='当前库位')
    target_location = models.CharField(max_length=50, verbose_name='目标库位')
    message = models.TextField(verbose_name='消息')
    working = models.IntegerField(default = 1,verbose_name='工作状态')
    status = models.IntegerField(choices=TASK_STATUS, default=100, verbose_name='状态')

    create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    is_delete = models.BooleanField(default=False, verbose_name='是否删除')

    class Meta:
        db_table = 'container_wcs'
        verbose_name = 'ContainerWCS'
        verbose_name_plural = "ContainerWCS"
        ordering = ['-create_time']
    
    def to_dict(self):
        return {
            'container': self.container,
            'current_location': self.current_location,
            'month' : self.month,
            'target_location': self.target_location,
            'tasktype': self.tasktype,
            'taskid': self.taskid,
            'taskNumber': self.tasknumber-20000000000,
            'message': self.message,
            'container': self.container,
            'status': self.status
        }
    def __str__(self):
        return f"{self.taskid} - {self.get_status_display()}"
# 这里的批次详情是主入库申请单下的子批次
class TaskModel(models.Model):
    
    task_wcs = models.ForeignKey(ContainerWCSModel, on_delete=models.CASCADE, related_name='tasks')
    batch_detail = models.ForeignKey(BoundDetailModel, on_delete=models.CASCADE, verbose_name='批次详情')
    container_detail = models.ForeignKey(ContainerDetailModel, on_delete=models.CASCADE, verbose_name='托盘明细')

    class Meta:
        db_table = 'task'
        verbose_name = 'Task'
        verbose_name_plural = "Task"
        ordering = ['-id']

class out_batch_detail(models.Model):
    out_bound = models.ForeignKey(BoundListModel, on_delete=models.CASCADE, related_name='out_batch_details')
    container = models.ForeignKey(ContainerListModel, on_delete=models.CASCADE, related_name='out_batch_details')
    container_detail = models.ForeignKey(ContainerDetailModel, on_delete=models.CASCADE, verbose_name='托盘明细')
    out_goods_qty = models.IntegerField(verbose_name='数量')
    last_out_goods_qty = models.IntegerField(verbose_name='上次出库数量', default=0)
    working = models.IntegerField(default = 1,verbose_name='工作状态')
    is_delete = models.BooleanField(default=False, verbose_name='是否删除')
    class Meta:
        db_table = 'out_batch_detail'
        verbose_name = 'OutBatchDetail'
        verbose_name_plural = "OutBatchDetail"
        ordering = ['container']