package com.cf.imes.module.plan.service.orderImport.consumer;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.cf.imes.framework.common.enums.OrderPackageStatusEnum;
import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil;
import com.cf.imes.framework.common.util.json.JsonUtils;
import com.cf.imes.framework.id.core.util.SnowflakeIdWorker3rd;
import com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants;
import com.cf.imes.framework.mybatis.core.generator.SnowFlakeGenerator;
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
import com.cf.imes.framework.redis.constants.RedisKeyConstants;
import com.cf.imes.framework.redis.util.RedisLockUtil;
import com.cf.imes.module.executor.enums.OrderImportStatusEnum;
import com.cf.imes.module.executor.enums.OrderImportTaskStatusEnum;
import com.cf.imes.module.executor.enums.OrderImportTmpDataTypeEnum;
import com.cf.imes.module.executor.enums.OrderStatusEnum;
import com.cf.imes.module.plan.dal.dataobject.order.OrderDO;
import com.cf.imes.module.plan.dal.dataobject.orderImport.OrderImportTaskDO;
import com.cf.imes.module.plan.dal.dataobject.orderImport.OrderImportTempDataDO;
import com.cf.imes.module.plan.dal.mysql.goods.GoodsMapper;
import com.cf.imes.module.plan.dal.mysql.order.OrderMapper;
import com.cf.imes.module.plan.dal.mysql.orderBody.OrderBodyMapper;
import com.cf.imes.module.plan.dal.mysql.orderGroup.OrderGroupMapper;
import com.cf.imes.module.plan.dal.mysql.orderImport.OrderImportTaskMapper;
import com.cf.imes.module.plan.dal.mysql.orderImport.OrderImportTempDataMapper;
import com.cf.imes.module.plan.dal.mysql.orderItem.OrderItemMapper;
import com.cf.imes.module.plan.dal.mysql.orderParts.OrderPartsMapper;
import com.cf.imes.module.plan.dal.mysql.orderParts.PartsMapper;
import com.cf.imes.module.plan.dal.mysql.plate.PlateGoodMapper;
import com.cf.imes.module.plan.dal.mysql.plate.PlateMapper;
import com.cf.imes.module.plan.dal.mysql.rawgoods.RawGoodsMapper;
import com.cf.imes.module.plan.service.customplateno.CustomPlateNoGenerateService;
import com.cf.imes.module.plan.service.order.OrderInputProcessor;
import com.cf.imes.module.plan.service.orderImport.factory.DefaultXmlOrderImportFactory;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import jakarta.annotation.Resource;

import java.time.LocalDate;
import java.util.Objects;
import java.util.Optional;

import static com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_IMPORT_ORDER_NOT_EXISTS;
import static com.cf.imes.module.plan.enums.ErrorCodeConstants.ORDER_IMPORT_FAIL;
import static com.cf.imes.module.plan.enums.ErrorCodeConstants.ORDER_IMPORT_ORGANID_NOT_EXISTS;

/**
 * 默认excel导入生产单消费者
 *
 * @author Gqr
 * @since 2025/2/19 16:22
 */
@Component
@Slf4j
public class DefaultXmlOrderImportConsumer {
    @Resource
    private OrderImportTaskMapper orderImportTaskMapper;

    @Resource
    private OrderImportTempDataMapper orderImportTempDataMapper;

    @Resource
    private OrderMapper orderMapper;

    @Resource
    private RedisLockUtil redisLockUtil;

    @Resource
    private SnowFlakeGenerator snowFlakeGenerator;

    @Resource
    private SnowflakeIdWorker3rd idWorker;

    @Resource
    private GoodsMapper goodsMapper;

    @Resource
    private RawGoodsMapper rawGoodsMapper;

    @Resource
    private OrderPartsMapper orderPartsMapper;

    @Resource
    private OrderBodyMapper orderBodyMapper;

    @Resource
    private OrderGroupMapper orderGroupMapper;

    @Resource
    private PlateMapper plateMapper;

    @Resource
    private OrderItemMapper orderItemMapper;

    @Resource
    private PlateGoodMapper plateGoodMapper;

    @Resource
    private OrderInputProcessor orderInputProcessor;

    @Resource
    private PartsMapper partsMapper;

    @Resource
    private CustomPlateNoGenerateService customPlateNoGenerateService;

    @RabbitListener(queues = RabbitMqConstants.ORDER_IMPORT_DEFAULT_XML_QUEUE)
    @DS("imes_prod")
    @Transactional(rollbackFor = Exception.class)
    public void orderImport(String message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws Exception {
        log.info("====================【生产单默认xml导入收到消息：{}】====================", message);
        Long organId = null;
        Long taskId = Long.parseLong(message);
        try {
            organId = OrganContextHolder.getOrganId();
            if (ObjectUtil.isNull(organId)) {
                throw ServiceExceptionUtil.exception(ORDER_IMPORT_ORGANID_NOT_EXISTS);
            }
            // 确认任务，更新状态为消费成功，没有找到任务中断后续消费
            OrderImportTaskDO orderImportTaskDO = confirmOrderImport(taskId);
            if (ObjectUtil.isNull(orderImportTaskDO)) {
                return;
            }
            // 创建生产单
            OrderDO orderDO = createOrder(taskId);
            log.info("====================【生产单默认xml导入处理临时数据开始】====================");
            // 创建工厂
            DefaultXmlOrderImportFactory defaultExcelOrderImportFactory = new DefaultXmlOrderImportFactory(taskId, orderDO, organId, orderImportTaskDO.getCreator(),
                    snowFlakeGenerator, idWorker, orderImportTaskMapper, orderImportTempDataMapper, goodsMapper, rawGoodsMapper, orderPartsMapper,
                    orderBodyMapper, orderGroupMapper, plateMapper, orderItemMapper, plateGoodMapper, orderInputProcessor, partsMapper, customPlateNoGenerateService);
            // 解析临时表数据
            defaultExcelOrderImportFactory.analyzeTempData();
            log.info("====================【生产单默认xml导入处理临时数据结束】====================");
        } catch (Exception e) {
            // 确认消息进入死信队列
            channel.basicNack(deliveryTag, false, false);
            log.error( ORDER_IMPORT_FAIL.getMsg(), e);
            throw e;
        } finally {
            // 手动确认消息接收
            channel.basicAck(deliveryTag, false);
            // 导入锁解锁
            redisLockUtil.releaseLock(String.format(RedisKeyConstants.ORDER_IMPORT_LOCK_KEY, organId), message);
        }
    }

    /**
     * 确认导入任务，更新任务状态
     *
     * @param taskId
     */
    private OrderImportTaskDO confirmOrderImport(Long taskId) {
        boolean taskExist = false;
        OrderImportTaskDO orderImportTaskDO = null;
        // 线程每1s查询一次，查三次没有就提示任务不存在
        for (int i = 0; i < 3; i++) {
            orderImportTaskDO = orderImportTaskMapper.selectById(taskId);
            if (ObjectUtil.isNotNull(orderImportTaskDO)) {
                taskExist = true;
                break;
            } else {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    log.error("====================【线程中断异常】====================");
                }
            }
        }
        if (taskExist) {
            // 更新状态为消费成功
            orderImportTaskMapper.update(new LambdaUpdateWrapper<OrderImportTaskDO>().eq(OrderImportTaskDO::getId, taskId).set(OrderImportTaskDO::getStatus, OrderImportTaskStatusEnum.CONSUME_SUCCESS.getStatus()));
        } else {
            String taskNotExistNotify = String.format("%s不存在的导入任务，消费中止", taskId);
            // 更新状态为消费成功，导入失败
            orderImportTaskMapper.update(
                    new LambdaUpdateWrapper<OrderImportTaskDO>()
                            .eq(OrderImportTaskDO::getId, taskId)
                            .set(OrderImportTaskDO::getStatus, OrderImportTaskStatusEnum.CONSUME_SUCCESS.getStatus())
                            .set(OrderImportTaskDO::getImportStatus, OrderImportStatusEnum.IMPORT_FAIL.getStatus())
                            .set(OrderImportTaskDO::getResult, taskNotExistNotify)
            );
            log.error(String.format("====================【%s】====================", taskNotExistNotify));
        }
        return orderImportTaskDO;
    }

    /**
     * 创建生产单
     *
     * @param taskId
     * @return
     */
    private OrderDO createOrder(Long taskId) {
        // 查询临时表中的order
        LambdaQueryWrapper<OrderImportTempDataDO> orderTempData = new LambdaQueryWrapper<OrderImportTempDataDO>()
                .eq(OrderImportTempDataDO::getTaskId, taskId)
                .eq(OrderImportTempDataDO::getType, OrderImportTmpDataTypeEnum.ORDER.getType())
                .eq(OrderImportTempDataDO::getSort, 0);
        OrderImportTempDataDO orderImportTempDataDO = orderImportTempDataMapper.selectOne(orderTempData);
        // 不是新单不用创建
        if (ObjectUtil.isNotNull(orderImportTempDataDO) && ObjectUtil.isNotNull(orderImportTempDataDO.getOrderId())) {
            Long existOrderId = orderImportTempDataDO.getOrderId();
            // 校验生产单id
            OrderDO orderDO = orderMapper.selectById(existOrderId);
            Optional.ofNullable(orderDO).orElseThrow(() -> ServiceExceptionUtil.exception(ORDER_IMPORT_ORDER_NOT_EXISTS, existOrderId));
            // 更新补板生产单属性
            updateOrder(orderDO);
            return orderDO;
        }
        // 取临时order数据，detail转orderDO，插入新增orderDO
        String orderTempDetail = JsonUtils.unzipString(orderImportTempDataDO.getDetail());
        OrderDO newOrder = JSON.parseObject(orderTempDetail, OrderDO.class);
        Long orderId = (Long) snowFlakeGenerator.nextId(null);
        newOrder.setId(orderId);
        orderMapper.insert(newOrder);
        // 生产单id更新到导入任务表
        orderImportTaskMapper.update(new LambdaUpdateWrapper<OrderImportTaskDO>()
                .eq(OrderImportTaskDO::getId, taskId)
                .set(OrderImportTaskDO::getOrderId, orderId));
        return newOrder;
    }

    /**
     * 更新补板生产单的属性
     *
     * @param orderDO
     */
    public void updateOrder(OrderDO orderDO) {
        // 发货日期校验
        LocalDate orderDate = LocalDate.from(orderDO.getOrderDate());
        LocalDate deliveryDate = LocalDate.from(orderDO.getDeliveryDate());
        if (deliveryDate.isBefore(orderDate)) {
            // 将 deliveryDate 设置为 orderDate 后的第 30 天
            deliveryDate = orderDate.plusMonths(1);
        }
        orderDO.setDeliveryDate(deliveryDate.atStartOfDay());
        if (Objects.equals(orderDO.getStatus(), OrderStatusEnum.EMPTY.getStatus())) {
            orderDO.setStatus(OrderStatusEnum.NEW_ORDER.getStatus());
        }
        if (Objects.equals(orderDO.getStatus(), OrderStatusEnum.FINISH_PRODUCTION.getStatus())) {
            orderDO.setStatus(OrderStatusEnum.IN_PRODUCTION.getStatus());
        }
        if (Objects.equals(orderDO.getPackaged(), OrderPackageStatusEnum.PACKAGED.getStatus())) {
            orderDO.setPackaged(OrderPackageStatusEnum.PACKAGED.getStatus());
        }
        orderMapper.updateById(orderDO);
    }
}
