package com.fizz.business.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fizz.business.constants.CommonConstants;
import com.fizz.business.constants.enums.RollerPositionEnum;
import com.fizz.business.constants.enums.RollerTypeEnum;
import com.fizz.business.domain.*;
import com.fizz.business.mapper.RollDataMapper;
import com.fizz.business.service.*;
import com.fizz.business.vo.OnlineRollDataVO;
import com.fizz.business.vo.ReadyRollDataVO;

import com.ruoyi.common.utils.bean.BeanUtils;
import org.apache.commons.compress.utils.Lists;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.core.MessagePropertiesBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class RollDataServiceImpl extends ServiceImpl<RollDataMapper, RollData> implements RollDataService {

    @Resource
    PlantConfigService plantConfigService;

    @Resource
    ShiftHistoryService shiftHistoryService;

    @Resource
    RollHistoryService rollHistoryService;

    @Resource
    RabbitTemplate rabbitTemplate;

    @Resource
    RollChangeCycleService rollChangeCycleService;

    @Override
    public List<RollData> getList(String position,String type,String status) {
        QueryWrapper<RollData> queryWrapper = new QueryWrapper<>();
        if(ObjectUtil.isNotEmpty(position)){
            queryWrapper.eq("position", position);
        }
        if(ObjectUtil.isNotEmpty(type)){
            queryWrapper.eq("type", type);
        }
        if(ObjectUtil.isNotEmpty(status)){
            queryWrapper.eq("status", status);
        }
        queryWrapper.last(" order by FIELD(CONCAT(POSITION, '_', TYPE), " +
                "'TOP_BACKUP', 'TOP_INTERMEDIATE', 'TOP_WORK', " +
                "'BOTTOM_WORK','BOTTOM_INTERMEDIATE', 'BOTTOM_BACKUP')");
        return this.list(queryWrapper);
    }

    @Override
    public List<ReadyRollDataVO> getReadyRollList(String position,String type, String status) {
        List<ReadyRollDataVO> readyRollDataVOList = new ArrayList<>();
        List<RollData> rollDataList = getList(position, type,status);
        for (RollData rollData : rollDataList) {
            ReadyRollDataVO readyRollDataVO = new ReadyRollDataVO();
            // 使用 BeanUtils 复制属性
            BeanUtils.copyProperties(rollData, readyRollDataVO);
            readyRollDataVO.setPosition(RollerPositionEnum.valueOf(rollData.getPosition()));
            readyRollDataVO.setType(RollerTypeEnum.valueOf(rollData.getType()));
            readyRollDataVOList.add(readyRollDataVO);
        }
        return readyRollDataVOList;
    }

    @Override
    public Map<String,ReadyRollDataVO> getAllReadyRollList() {
        List<ReadyRollDataVO> readyRollDataVOList = new ArrayList<>();
        List<RollData> rollDataList = getList(null,null,"STANDBY");
        for (RollData rollData : rollDataList) {
            ReadyRollDataVO readyRollDataVO = new ReadyRollDataVO();
            // 使用 BeanUtils 复制属性
            BeanUtils.copyProperties(rollData, readyRollDataVO);
            readyRollDataVO.setPosition(RollerPositionEnum.valueOf(rollData.getPosition()));
            readyRollDataVO.setType(RollerTypeEnum.valueOf(rollData.getType()));
            readyRollDataVOList.add(readyRollDataVO);
        }
        //补充6个位置
        return readyRollDataVOList.stream()
                .collect(Collectors.toMap(
                        ReadyRollDataVO->ReadyRollDataVO.getPosition().getValue()+ReadyRollDataVO.getType().getValue()
                        , obj -> obj,(key1, key2)->key1));
    }

    @Override
    public List<OnlineRollDataVO> getOnlineRollList() {
        Map<String, PlantConfig> plantConfigMap = plantConfigService.getAllConfig();

        List<OnlineRollDataVO> readyRollDataVOList = new ArrayList<>();
        List<RollData> rollDataList = getList(null, null,"ONLINE");
        List<RollChangeCycle> changeList = rollChangeCycleService.list();
        for (RollData rollData : rollDataList) {
            OnlineRollDataVO onlineRollDataVO = new OnlineRollDataVO();
            // 使用 BeanUtils 复制属性
            BeanUtils.copyProperties(rollData, onlineRollDataVO);
            onlineRollDataVO.setPosition(RollerPositionEnum.valueOf(rollData.getPosition()));
            onlineRollDataVO.setType(RollerTypeEnum.valueOf(rollData.getType()));

            RollChangeCycle rollChangeCycle = changeList.stream().filter(item->item.getType().equals(rollData.getType())
                    &&item.getPosition().equals(rollData.getPosition()))
                    .findFirst()
                    .orElse(null);
            if(rollChangeCycle!=null)
            {
                onlineRollDataVO.setUsableLength(rollChangeCycle.getRolledLength());
                onlineRollDataVO.setLeftLength(rollChangeCycle.getRolledLength()-onlineRollDataVO.getRolledLength());

                onlineRollDataVO.setUsableWeight(rollChangeCycle.getRolledWeight());
                onlineRollDataVO.setLeftWeight(rollChangeCycle.getRolledWeight()-onlineRollDataVO.getRolledWeight());
            }

//            String lengthKey="";
//            String weightKey="";
//            switch(rollData.getType()){
//                case "BACKUP":
//                    lengthKey = "MAX_BUR_ROLLER_LENGTH";
//                    weightKey = "MAX_BUR_ROLLER_WEIGHT";
//                    break;
//                case "INTERMEDIATE":
//                    lengthKey = "MAX_INTERMEDIATE_ROLLER_LENGTH";
//                    weightKey = "MAX_INTERMEDIATE_ROLLER_WEIGHT";
//                    break;
//                case "WORK":
//                    lengthKey = "MAX_WORK_ROLLER_LENGTH";
//                    weightKey = "MAX_WORK_ROLLER_WEIGHT";
//                    break;
//            }
//            //轧制长度，轧制重量
//            if(plantConfigMap.containsKey(lengthKey)){
//                PlantConfig plantConfig = plantConfigMap.get(lengthKey);
//                double value = Double.parseDouble(plantConfig.getValue());
//                onlineRollDataVO.setUsableLength(value);
//                onlineRollDataVO.setLeftLength(value-onlineRollDataVO.getRolledWeight());
//            }
//            if(plantConfigMap.containsKey(weightKey)){
//                PlantConfig plantConfig = plantConfigMap.get(weightKey);
//                double value = Double.parseDouble(plantConfig.getValue());
//                onlineRollDataVO.setRolledWeight(value);
//                onlineRollDataVO.setLeftLength(value-onlineRollDataVO.getRolledWeight());
//            }
            readyRollDataVOList.add(onlineRollDataVO);
        }
        return readyRollDataVOList;
    }

    @Override
    public String BackupRoll(List<ReadyRollDataVO> rollList) {
        if(ObjectUtil.isEmpty(rollList)){
            return "轧辊数量为空，无法备辊";
        }
        //统一检查所有轧辊状态
        List<String> rollidList = rollList.stream()
                .map(ReadyRollDataVO::getRollid)
                .collect(Collectors.toList());
        List<RollData> rollDataList = this.baseMapper.selectBatchIds(rollidList);

        if(rollDataList.stream()
                .anyMatch(item->item.getStatus().equals("ONLINE"))){
            return "存在轧辊已在线，无法备辊";
        }
        Map<String, PlantConfig> plantConfigMap = plantConfigService.getAllConfig();
        //检查是否成对
        //检查辊径大小
        //检查辊径差
        List<String> result = new ArrayList<>();
        //工作辊
        checkRollDia( plantConfigMap,rollList,result,"WORK");
        checkRollDia( plantConfigMap,rollList,result,"INTERMEDIATE");
        checkRollDia( plantConfigMap,rollList,result,"BACKUP");

        //清楚所有已有备辊，添加新备辊,有则更新数据,没有则新增
        if(ObjectUtil.isEmpty(result)) {
            lambdaUpdate().set(RollData::getStatus, "OFFLINE")
                    .eq(RollData::getStatus, "STANDBY")
                    .update();

            List<RollData> newDataList = Lists.newArrayList();
            rollList.forEach(item -> {

                RollData temp = rollDataList.stream().filter(n -> n.getRollid().equals(item.getRollid()))
                        .findFirst().orElse(RollData.builder()
                                .rollid(item.getRollid())
                                .position(item.getPosition().getValue())
                                .type(item.getType().getValue())
                                .seton("CRM")
                                .standid(1)
                                .grindCount(0)
                                .build());
                //更新辊径、凸度和粗糙度
                temp.setDiameter(item.getDiameter());
                temp.setCrown(item.getCrown());
                temp.setRough(item.getRough());
                temp.setStatus("STANDBY");
                newDataList.add(temp);
            });
            this.saveOrUpdateBatch(newDataList);

        }
        return String.join(",",result);
    }

    @Override
    public List<OnlineRollDataVO> onlineRoll() {
        List<RollData> standByRollList = getList(null, null,"STANDBY");
        List<RollData> onlineRollList = getList(null, null,"ONLINE");
        if(ObjectUtil.isEmpty(standByRollList)){
            return getOnlineRollList();
        }
        ShiftHistory shiftHistory = shiftHistoryService.getCurrent();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        String changeID = LocalDateTime.now().format(dateTimeFormatter);
        List<RollHistory> rollHistoryList =Lists.newArrayList();
        List<RollData> changeRollList =Lists.newArrayList();
        //更换轧辊
        standByRollList.forEach(item->{
            //上线卷
            item.setStatus("ONLINE");
            item.setGrindCount(item.getGrindCount()+1);
            item.setRolledCount(0);
            item.setRolledWeight(0d);
            item.setRolledLength(0d);
            item.setInstalTime(LocalDateTime.now());
            item.setDeinstalTime(LocalDateTime.now());
            changeRollList.add(item);

            RollHistory rollHistoryOn = RollHistory.builder().build();
            BeanUtils.copyProperties(item, rollHistoryOn);
            rollHistoryOn.setChangeid(changeID);
            rollHistoryOn.setShift(shiftHistory.getShift());
            rollHistoryOn.setCrew(shiftHistory.getCrew());
            rollHistoryOn.setChangeType("ON");
            rollHistoryOn.setChangeTime(LocalDateTime.now());
            rollHistoryList.add(rollHistoryOn);

            //下线卷
            RollData onlineRoll = onlineRollList.stream().filter(n->n.getPosition().equals(item.getPosition())
                            &&n.getType().equals(item.getType()))
                    .findFirst().orElse(null);
            if(ObjectUtil.isNotNull(onlineRoll)){
                onlineRoll.setStatus("OFFLINE");
                onlineRoll.setDeinstalTime(LocalDateTime.now());
                changeRollList.add(onlineRoll);

                RollHistory rollHistoryOff = RollHistory.builder().build();
                BeanUtils.copyProperties(onlineRoll, rollHistoryOff);
                rollHistoryOff.setChangeid(changeID);
                rollHistoryOff.setShift(shiftHistory.getShift());
                rollHistoryOff.setCrew(shiftHistory.getCrew());
                rollHistoryOff.setChangeType("OFF");
                rollHistoryOff.setChangeTime(LocalDateTime.now());
                rollHistoryList.add(rollHistoryOff);
            }

        });
        this.updateBatchById(changeRollList);
        rollHistoryService.saveBatch(rollHistoryList);

        //发送MQ
        MessageProperties props = MessagePropertiesBuilder.newInstance()
                .setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN)
                .setMessageId("ROLL_CHANGE")
                .build();

        JSONObject msg = new JSONObject();
        msg.put("data","ROLL_CHANGE");
        rabbitTemplate.send(CommonConstants.RabbitMQ.SEND_MODEL,new Message(JSONObject.toJSONString(msg).getBytes(StandardCharsets.UTF_8),props));

        return getOnlineRollList();
    }

    private void checkRollDia(Map<String, PlantConfig> plantConfigMap,List<ReadyRollDataVO> rollList,List<String> result,String type){
        String name = "";
        String maxValueKey = "";
        String minValueKey = "";
        String diffValueKey = "";

        switch(type){
            case "BACKUP":
                maxValueKey = "MAX_BR_DIA";
                minValueKey = "MIN_BR_DIA";
                diffValueKey = "MAX_BR_DIA_DIFF";
                name = "支撑辊";
                break;
            case "INTERMEDIATE":
                maxValueKey = "MAX_IR_DIA";
                minValueKey = "MIN_IR_DIA";
                diffValueKey = "MAX_IR_DIA_DIFF";
                name = "中间辊";
                break;
            case "WORK":
                maxValueKey = "MAX_WR_DIA";
                minValueKey = "MIN_WR_DIA";
                diffValueKey = "MAX_WR_DIA_DIFF";
                name = "工作辊";
                break;
        }

        List<ReadyRollDataVO> rolls = rollList.stream()
                .filter(item->item.getType().getValue().equals(type)&&ObjectUtil.isNotEmpty(item.getRollid()))
                .collect(Collectors.toList());
        if(rolls.size()>0){
            //工作辊成对更换
            double rollDia1;
            double rollDia2;
            if(type.equals("WORK")||type.equals("INTERMEDIATE")) {
                if (rolls.size() != 2) {
                    result.add(String.format("%s必须成对更换", name));
                    return;
                } else {
                    if (rolls.get(0).getPosition().equals(rolls.get(1).getPosition())) {
                        result.add(String.format("%s备辊位置重复", name));
                        return;
                    }
                    rollDia1 = rolls.get(0).getDiameter();
                    rollDia2 = rolls.get(1).getDiameter();
                }
            }
            else{
                if(rolls.size()>2){
                    result.add(String.format("%s备辊数量错误",name));
                    return;
                }else {
                    rollDia1 = rolls.get(0).getDiameter();
                    if(rolls.size()==2) {
                        if (rolls.get(0).getPosition().equals(rolls.get(1).getPosition())) {
                            result.add(String.format("%s备辊位置重复", name));
                            return;
                        }
                        rollDia2 = rolls.get(1).getDiameter();
                    }else {
                        //单个备辊，和在线辊比较
                        rollDia2 = rollDia1;
                        String nextPosition = rolls.get(0).getPosition().equals("TOP")?"BOTTOM":"TOP";
                        List<RollData> onlineList =  getList(nextPosition,type,"ONLINE");
                        if(onlineList.size()>0){
                            rollDia2 = onlineList.get(0).getDiameter();
                        }
                    }
                }
            }
            //最大值
            if(plantConfigMap.containsKey(maxValueKey)){
                double value = Double.parseDouble(plantConfigMap.get(maxValueKey).getValue());
                if(rollDia1>value||rollDia2>value){
                    result.add(String.format("%s辊径超限[max：%.2f]",name,value));
                }
            }
            //最小值
            if(plantConfigMap.containsKey(minValueKey)){
                double value = Double.parseDouble(plantConfigMap.get(minValueKey).getValue());
                if(rollDia1<value||rollDia2<value){
                    result.add(String.format("%s辊径超限[min：%.2f]",name,value));
                }
            }
            //差值
            if(plantConfigMap.containsKey(diffValueKey)){
                double value = Double.parseDouble(plantConfigMap.get(diffValueKey).getValue());
                if(Math.abs(rollDia1-rollDia2)>value){
                    result.add(String.format("{%s辊径超限[diff：%.2f]",name,value));
                }
            }
        }
    }
}
