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.ServiceException;
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.config.ChenfengCacheProperties;
import com.cf.imes.framework.redis.constants.RedisKeyConstants;
import com.cf.imes.framework.redis.util.RedisLockUtil;
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.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.orderImport.OrderImportTaskService;
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 jakarta.annotation.Resource;
import org.springframework.transaction.support.TransactionTemplate;

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.executor.enums.ErrorCodeConstants.ORDER_IMPORT_ORGAN_LOCK_ERROR;
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 OrderImportTaskService orderImportTaskService;

    @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 CustomPlateNoGenerateService customPlateNoGenerateService;

    @Resource
    private ChenfengCacheProperties chenfengCacheProperties;

    @Resource
    private TransactionTemplate transactionTemplate;

    @RabbitListener(queues = RabbitMqConstants.ORDER_IMPORT_DEFAULT_XML_QUEUE)
    @DS("imes_prod")
    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);
        boolean lockResult = true;
        OrderImportTaskDO orderImportTaskDO = null;

        try {
            // 手动确认消息接收
            channel.basicAck(deliveryTag, false);

            organId = OrganContextHolder.getOrganId();
            if (ObjectUtil.isNull(organId)) {
                throw new ServiceException(ORDER_IMPORT_ORGANID_NOT_EXISTS);
            }

            // 检查机构导入锁
            String importLockKey = String.format(RedisKeyConstants.ORDER_IMPORT_LOCK_KEY, organId);
            lockResult = redisLockUtil.acquireLock(importLockKey, String.valueOf(taskId), chenfengCacheProperties.getLockTimeout());
            if (!lockResult) {
                throw new ServiceException(ORDER_IMPORT_ORGAN_LOCK_ERROR);
            }

            // 确认任务，更新状态为消费成功，没有找到任务中断后续消费
            orderImportTaskDO = orderImportTaskService.confirmOrderImport(taskId);
            if (ObjectUtil.isNull(orderImportTaskDO)) {
                return;
            }

            Long finalOrganId = organId;
            String creator = orderImportTaskDO.getCreator();
            transactionTemplate.execute(status -> {
                try {
                    // 创建订单
                    OrderDO orderDO = createOrder(taskId);
                    log.info("====================【订单默认xml导入处理临时数据开始】====================");
                    // 创建工厂
                    DefaultXmlOrderImportFactory defaultExcelOrderImportFactory = new DefaultXmlOrderImportFactory(taskId, orderDO, finalOrganId, creator,
                            snowFlakeGenerator, idWorker, orderImportTaskMapper, orderImportTempDataMapper, orderMapper, goodsMapper, rawGoodsMapper, orderPartsMapper,
                            orderBodyMapper, orderGroupMapper, plateMapper, orderItemMapper, plateGoodMapper, customPlateNoGenerateService);
                    // 解析临时表数据
                    defaultExcelOrderImportFactory.analyzeTempData();
                    log.info("====================【订单默认xml导入处理临时数据结束】====================");
                } catch (Exception e) {

                    status.setRollbackOnly();

                    throw e;
                }

                return null;
            });
        } catch (Exception e) {
            log.error( ORDER_IMPORT_FAIL.getMsg(), e);
            orderImportTaskService.updateImportTaskFail(orderImportTaskDO, e);
            throw e;
        } finally {
            if (lockResult) {
                // 导入锁解锁
                redisLockUtil.releaseLock(String.format(RedisKeyConstants.ORDER_IMPORT_LOCK_KEY, organId), message);
            }
        }
    }

    /**
     * 创建订单
     *
     * @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(() -> new ServiceException(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);
        // todo 后续可能有子单需求？目前只创建主单
        newOrder.setRootId(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);
    }
}
