package com.cf.imes.module.executor.service.customplateno;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.cf.imes.framework.common.exception.ServiceException;
import com.cf.imes.framework.common.pojo.CommonResult;
import com.cf.imes.framework.common.util.json.JsonUtils;
import com.cf.imes.module.executor.dal.dataobject.order.OrderDO;
import com.cf.imes.module.executor.dal.dataobject.plate.PlateDO;
import com.cf.imes.module.executor.dal.mysql.order.OrderMapper;
import com.cf.imes.module.executor.enums.ErrorCodeConstants;
import com.cf.imes.module.executor.service.customplateno.vo.CustomPlateNoGenerateConfigVO;
import com.cf.imes.module.executor.service.customplateno.vo.CustomPlateNoRuleVO;
import com.cf.imes.module.executor.service.customplateno.vo.OrderCustomPlateNoSeqVO;
import com.cf.imes.module.executor.service.customplatenorule.CustomPlateNoGenerateRuleService;
import com.cf.imes.module.executor.service.order.OrderService;
import com.cf.imes.module.system.api.customplateno.CustomPlateNoSeqApi;
import com.cf.imes.module.system.api.customplateno.dto.CustomPlateNoSeqDTO;
import com.cf.imes.module.system.api.systemconfig.SystemConfigApi;
import com.cf.imes.module.system.api.systemconfig.dto.SystemConfigRespDTO;
import com.cf.imes.module.system.enums.customplateno.CustomPlateNoRuleCodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;

import jakarta.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Optional;

/**
 * @author Gqr
 * @since 2024/11/14 11:41
 */
@Service
@Slf4j
public class CustomPlateNoGenerateServiceImpl implements CustomPlateNoGenerateService {

    @Resource
    @Lazy
    private OrderService orderService;

    @Resource
    private SystemConfigApi systemConfigApi;

    @Resource
    private CustomPlateNoSeqApi customPlateNoSeqApi;

    @Resource
    private List<CustomPlateNoGenerateRuleService> ruleServices;

    @Resource
    private OrderMapper orderMapper;

    private static final DateTimeFormatter YEAR_FORMATTER = DateTimeFormatter.ofPattern("yyyy");
    private static final DateTimeFormatter MONTH_FORMATTER = DateTimeFormatter.ofPattern("yyyyMM");
    private static final DateTimeFormatter DAY_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");

    @Override
    public void generateCustomPlateNo(OrderDO orderDO, List<PlateDO> plateDOList, boolean newOrder) {
        // 执行时间记录
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        Long orderId = orderDO.getId();
        // 1、获取生产配置
        CustomPlateNoGenerateConfigVO generateConfig = getGenerateConfig(orderId);
        // 如果没有查到配置规则就不做后续生成操作了
        List<CustomPlateNoRuleVO> orgCustomPlateNoRuleVOList = generateConfig.getOrgCustomPlateNoRuleVOList();
        // 如果没有查到机构下配置就不做后续生成操作了
        Long orgCustomPlateNoConfigId = generateConfig.getOrgCustomPlateNoConfigId();
        if (ObjectUtil.isNull(orgCustomPlateNoConfigId) || CollUtil.isEmpty(orgCustomPlateNoRuleVOList)) {
            return;
        }

        // 开始生成时记录时间，用于后续年月日复位、上次年月日记录等
        LocalDateTime now = LocalDateTime.now();
        orgCustomPlateNoRuleVOList.forEach(rule -> rule.setNow(now));

        // 2、遍历小板列表，生成板编号
        for (int i = 0; i < plateDOList.size(); i++) {
            PlateDO plateDO = plateDOList.get(i);
            loopGenerateNo(orderId, plateDO, orgCustomPlateNoRuleVOList, generateConfig, i == 0);
        }

        // 3、保存订单序号json、设置订单所用配置id
        OrderCustomPlateNoSeqVO orderCustomPlateNoSeqVO = generateConfig.getOrderCustomPlateNoSeqVO();
        if (newOrder) {
            orderDO.setCustomPlatenoSeq(JSON.toJSONString(orderCustomPlateNoSeqVO));
            orderDO.setCustomPlatenoConfigId(orgCustomPlateNoConfigId);
        } else {
            // 已有订单更新序号
            orderMapper.update(new LambdaUpdateWrapper<OrderDO>().eq(OrderDO::getId, orderId).set(OrderDO::getCustomPlatenoSeq, JsonUtils.zipString(JSON.toJSONString(orderCustomPlateNoSeqVO))));
        }
        // 机构下序号配置同步
        CustomPlateNoSeqDTO orgCustomPlateNoSeqRespDTO = generateConfig.getOrgCustomPlateNoSeqRespDTO();
        orgCustomPlateNoSeqRespDTO.setLastOrderNo(orderId);
        orgCustomPlateNoSeqRespDTO.setLastYear(Integer.parseInt(YEAR_FORMATTER.format(now)));
        orgCustomPlateNoSeqRespDTO.setLastMonth(Integer.parseInt(MONTH_FORMATTER.format(now)));
        orgCustomPlateNoSeqRespDTO.setLastDay(Integer.parseInt(DAY_FORMATTER.format(now)));
        // 保存组织下全局序号配置
        CommonResult<Boolean> orgCustomPlateNoSeqModifyResult = customPlateNoSeqApi.modifyOrgCustomPlateNoSeq(orgCustomPlateNoSeqRespDTO);
        if (orgCustomPlateNoSeqModifyResult.isError() || !orgCustomPlateNoSeqModifyResult.getData().booleanValue()) {
            throw new ServiceException(ErrorCodeConstants.CUSTOM_PLATENO_GENERATE_ORG_CUSTOM_PLATENO_SEQ_MODIFY_ERROR);
        }
        stopWatch.stop();
        log.info("生成板编号耗时：{} seconds", stopWatch.getTotalTimeSeconds());
    }

    /**
     * 循环规则和板件列表生成编号
     *
     * @param orderId
     * @param plateDO
     * @param orgCustomPlateNoRuleVOList
     * @param generateConfig
     * @param
     */
    private void loopGenerateNo(Long orderId, PlateDO plateDO, List<CustomPlateNoRuleVO> orgCustomPlateNoRuleVOList, CustomPlateNoGenerateConfigVO generateConfig, boolean firstPlate) {
        // 遍历规则列表
        for (CustomPlateNoRuleVO plateNoRule : orgCustomPlateNoRuleVOList) {
            if (ObjectUtil.equal(CustomPlateNoRuleCodeEnum.CUSTOM.getRuleCode(), plateNoRule.getRuleCode())) {
                plateDO.getCustomPlateNoBuilder().append(Optional.ofNullable(plateNoRule.getStrValue()).orElse(""));
            }
            if (ObjectUtil.equal(CustomPlateNoRuleCodeEnum.DATE.getRuleCode(), plateNoRule.getRuleCode())) {
                String dateValue = plateNoRule.getDateValue();
                if (StringUtils.isNotEmpty(dateValue)) {
                    plateDO.getCustomPlateNoBuilder().append(plateNoRule.getNow().format(DateTimeFormatter.ofPattern(dateValue)));
                }
            }
            // 遍历规则生成服务列表，获取对应的规则服务
            for (CustomPlateNoGenerateRuleService ruleService : ruleServices) {
                if (ruleService.match(plateNoRule.getRuleCode())) {
                    generateConfig = ruleService.generateNo(orderId, plateNoRule, generateConfig, plateDO, firstPlate);
                    break;
                }
            }
        }
        plateDO.setCustomPlateNo(plateDO.getCustomPlateNoBuilder().toString());
    }

    /**
     * 根据订单id获取生成需要的配置
     *
     * @param orderId
     * @return 1、订单下的序号
     * 2、机构下的序号
     * 3、机构下全局配置的规则
     */
    private CustomPlateNoGenerateConfigVO getGenerateConfig(Long orderId) {
        // 生成自定义版编号所需配置
        CustomPlateNoGenerateConfigVO customPlateNoGenerateConfigVO = new CustomPlateNoGenerateConfigVO();

        // 机构下自定义板编号配置
        SystemConfigRespDTO orgCustomPlateNoConfig = null;
        // 订单下序号
        OrderCustomPlateNoSeqVO orderCustomPlateNoSeqVO = new OrderCustomPlateNoSeqVO();
        // 自定义板编号配置规则明细列表
        List<CustomPlateNoRuleVO> customPlateNoRuleVOS = List.of();
        // 查询机构的自定义版编号配置
        CommonResult<SystemConfigRespDTO> orgCustomPlateNoConfigResult = systemConfigApi.getOrgCustomPlateNoConfig();
        if (orgCustomPlateNoConfigResult.isSuccess()) {
            orgCustomPlateNoConfig = orgCustomPlateNoConfigResult.getData();
            customPlateNoRuleVOS = Optional.ofNullable(orgCustomPlateNoConfig)
                    .map(config -> JSON.parseArray(config.getSetting(), CustomPlateNoRuleVO.class))
                    .orElse(List.of());
            customPlateNoGenerateConfigVO.setOrgCustomPlateNoConfigId(Optional.ofNullable(orgCustomPlateNoConfig).map(SystemConfigRespDTO::getId).orElse(null));
        }

        OrderDO order = orderService.getOrder(orderId);
        if (ObjectUtil.isNotNull(order) && ObjectUtil.isNotNull(orgCustomPlateNoConfig)) {
            // 老单
            // 订单上的自定义板编号配置id和当前最新的对比，不同用订单号上的
            Long orderCustomPlatenoConfigId = order.getCustomPlatenoConfigId();
            if (ObjectUtil.isNotNull(orderCustomPlatenoConfigId) && ObjectUtil.notEqual(orgCustomPlateNoConfig.getId(), orderCustomPlatenoConfigId)) {
                CommonResult<SystemConfigRespDTO> previousCustomPlateNoConfig = systemConfigApi.getById(orderCustomPlatenoConfigId);
                if (previousCustomPlateNoConfig.isSuccess()) {
                    customPlateNoRuleVOS = JSON.parseArray(previousCustomPlateNoConfig.getData().getSetting(), CustomPlateNoRuleVO.class);
                }
            }

            // 上一次的订单内 自定义版编号序号
            orderCustomPlateNoSeqVO = JSON.parseObject(order.getCustomPlatenoSeq(), OrderCustomPlateNoSeqVO.class);
        }
        customPlateNoGenerateConfigVO.setOrderCustomPlateNoSeqVO(orderCustomPlateNoSeqVO);
        customPlateNoGenerateConfigVO.setOrgCustomPlateNoRuleVOList(customPlateNoRuleVOS);
        CommonResult<CustomPlateNoSeqDTO> orgCustomPlateNoSeq = customPlateNoSeqApi.getOrgCustomPlateNoSeq();
        if (orgCustomPlateNoSeq.isSuccess()) {
            customPlateNoGenerateConfigVO.setOrgCustomPlateNoSeqRespDTO(orgCustomPlateNoSeq.getData());
        }
        return customPlateNoGenerateConfigVO;
    }
}
