package com.junmp.jyzb.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.junmp.jyzb.Repository.SizeRepository;
import com.junmp.jyzb.api.bean.dto.EquipmentSizeDto;
import com.junmp.jyzb.api.bean.dto.FetchingDataDto.SizeDto;
import com.junmp.jyzb.api.bean.dto.MQDto;
import com.junmp.jyzb.api.bean.query.QueryEquipmentSizeReq;
import com.junmp.jyzb.api.bean.query.QueryEquipmentTypeReq;
import com.junmp.jyzb.api.bean.req.UpdateEquipmentSizeReq;
import com.junmp.jyzb.api.exception.enums.EquipmentExceptionEnum;
import com.junmp.jyzb.api.exception.enums.ProductExceptionEnum;
import com.junmp.jyzb.entity.EquipmentSize;
import com.junmp.jyzb.entity.EquipmentType;
import com.junmp.jyzb.entity.InventorySummary;
import com.junmp.jyzb.entity.WarehouseDev;
import com.junmp.jyzb.mapper.EquipmentCountSummaryMapper;
import com.junmp.jyzb.mapper.EquipmentTypeMapper;
import com.junmp.jyzb.mapper.PriceSumSummaryMapper;
import com.junmp.jyzb.service.EquipmentSizeService;
import com.junmp.jyzb.service.EquipmentTypeService;
import com.junmp.jyzb.service.InventorySummaryService;
import com.junmp.jyzb.service.WarehouseDevService;
import com.junmp.jyzb.utils.DateTimeUtil;
import com.junmp.jyzb.utils.RabbitMQSendMsg;
import com.junmp.v2.common.exception.base.ServiceException;
import com.junmp.v2.common.util.BeanPlusUtil;
import com.junmp.v2.db.api.factory.PageFactory;
import com.junmp.v2.db.api.factory.PageResultFactory;
import com.junmp.v2.db.api.page.PageResult;
import com.rabbitmq.client.AMQP;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import com.junmp.jyzb.mapper.EquipmentSizeMapper;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Service
public class EquipmentSizeServiceImpl extends ServiceImpl<EquipmentSizeMapper, EquipmentSize> implements EquipmentSizeService {

    @Resource
    private EquipmentSizeMapper equipmentSizeMapper;

    @Resource
    private EquipmentTypeMapper equipmentTypeMapper;

    @Resource
    private EquipmentTypeService equipmentTypeService;

    @Autowired
    private SizeRepository sizeRepository;

    @Resource
    private InventorySummaryService inventorySummaryService;

    @Resource
    private EquipmentCountSummaryMapper equipmentCountSummaryMapper;

    @Resource
    private PriceSumSummaryMapper priceSumSummaryMapper;

    @Resource
    private WarehouseDevService warehouseDevService;

    @Autowired
    private RabbitMQSendMsg MQ;

    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private RabbitAdmin rabbitAdmin;

    @Override
    public Object addEs() {
        QueryEquipmentTypeReq req =new QueryEquipmentTypeReq();
        req.setType(0);
        List<EquipmentSize> esDto=this.list();
        return sizeRepository.saveAll(esDto);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String addSize(UpdateEquipmentSizeReq req) {
        //判断输入的typeId是否存在，如果不存在抛出异常
        EquipmentType one = equipmentTypeService.getById(req.getTypeId());
        if (one==null){
            throw new ServiceException(EquipmentExceptionEnum.EQUIPMENT_TYPE_NOT_EXIST);
        }
        //判断同一个typeId下面是否有相同的name，如果有则添加失败
        List<EquipmentSize> list = list(new LambdaQueryWrapper<EquipmentSize>()
                .eq(EquipmentSize::getTypeId,req.getTypeId()));
        //将列表查询出来之后，将code码从string类型转成int类型，因为string类型比较code码会出现问题，只有转成int才能保证我能取道该装备类型的最大code然后在最大code的基础上新增一个号型
        List<String> collect = list.stream().map(EquipmentSize::getCode).collect(Collectors.toList());
        List<Integer> integerList = collect.stream()
                .map(Integer::parseInt)
                .sorted((a, b) -> Integer.compare(b, a)) // 按降序排列
                .collect(Collectors.toList());
        String code="1";
        if (integerList.size()>0){
            int i = integerList.get(0);
            code=String.valueOf(i+1);
            for (EquipmentSize size: list) {
                if (size.getName().equals(req.getName())){
                    throw new ServiceException(EquipmentExceptionEnum.EQUIPMENT_NAME_CODE_EXIST);
                }
            }
        }
        
        EquipmentSize size = new EquipmentSize();
        String sizeID=UUID.randomUUID().toString();
        BeanPlusUtil.copyProperties(req, size);
        size.setId(sizeID);
        size.setCode(code);
        size.setCreateTime(DateTimeUtil.getCurrentDateTime());
        size.setUpdateTime(DateTimeUtil.getCurrentDateTime());
        this.save(size);
        sizeRepository.save(size);
        //新增信息之后，将消息推送给所有本地主机
//        LambdaQueryWrapper<WarehouseDev> queryWrapper = new LambdaQueryWrapper<WarehouseDev>()
//                .select(WarehouseDev::getOrgId)
//                .groupBy(WarehouseDev::getOrgId);
//        List<WarehouseDev> list1 = warehouseDevService.list(queryWrapper);
//        List<String> orgIdsList = list1.stream()
//                .map(WarehouseDev::getOrgId)
//                .collect(Collectors.toList());
        String exchangeName="topicExchange";
        MQDto mqDto = new MQDto();
        mqDto.setApi("InfoChange");
        //更改类别，1为号型
        mqDto.setType(1);
        mqDto.setMessage("Adding sizeInfo");
        MQ.sendToExchange(exchangeName,"org",mqDto);

        //添加es
        sizeRepository.save(size);
        return sizeID+"||"+code;
    }

    @Override
    public EquipmentSize getOneSize(QueryEquipmentSizeReq req) {
        return this.getById(req);
    }

    @Override
    public Boolean deleteSize(UpdateEquipmentSizeReq req) {
        sizeRepository.deleteById(Long.valueOf(req.getId()));
        return this.removeById(req.getId());

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateSize(UpdateEquipmentSizeReq req) {
        //判断输入的typeId是否存在，如果不存在抛出异常
        EquipmentType one = equipmentTypeService.getById(req.getTypeId());
        if (one==null){
            throw new ServiceException(EquipmentExceptionEnum.EQUIPMENT_TYPE_NOT_EXIST);
        }
        EquipmentSize size = this.querySize(req);
        //判断两者的名称是否一致，如果一致，则直接改动summary表中的数据以及所有涉及到名称的装备数据表
        if (!size.getName().equals(req.getName())){
            inventorySummaryService.update(new LambdaUpdateWrapper<InventorySummary>()
                    .set(InventorySummary::getSizeName,req.getName())
                    .eq(InventorySummary::getSizeId,req.getId()));
            priceSumSummaryMapper.setSizeName(req.getId(),req.getName());
            equipmentCountSummaryMapper.setSizeName(req.getId(),req.getName());
        }

        BeanPlusUtil.copyProperties(req, size);
        size.setUpdateTime(DateTimeUtil.getCurrentDateTime());
        sizeRepository.save(size);

        String exchangeName="topicExchange";
        MQDto mqDto = new MQDto();
        mqDto.setApi("InfoChange");
        //更改类别，1为号型
        mqDto.setType(1);
        mqDto.setMessage("Updating sizeInfo");
        MQ.sendToExchange(exchangeName,"org",mqDto);

        //添加es
        sizeRepository.save(size);
        return this.updateById(size);
    }

    @Override
    public Boolean changeSizeState(UpdateEquipmentSizeReq req) {
        EquipmentSize size = this.querySize(req);
        size.setState(Integer.valueOf(req.getState()));
        sizeRepository.save(size);
        return this.updateById(size);
    }

    @Override
    public List<EquipmentSizeDto> getAllSize(QueryEquipmentSizeReq req) {
        LambdaQueryWrapper<EquipmentSize> wrapper = createWrapper(req);
        List<EquipmentSize> es = this.list(wrapper);

        List<EquipmentSizeDto> collect = es.stream().map(equipmentSize -> {
                            EquipmentSizeDto dto = new EquipmentSizeDto();
                            BeanPlusUtil.copyProperties(equipmentSize, dto);
                            return dto;}
                ).sorted(Comparator.comparing(dto -> Integer.parseInt(dto.getCode())))
                .collect(Collectors.toList());
        return collect;
    }
    @Override
    public PageResult<EquipmentSizeDto> getSizePages(QueryEquipmentSizeReq req) {
        Page<EquipmentSizeDto> page = PageFactory.getDefaultPage(req.getPageNo(), req.getPageSize());
        List<EquipmentSizeDto> voList= equipmentSizeMapper.getSizePage(req,page);
        page.setRecords(voList);
        return PageResultFactory.createPageResult(page);


    }

    //根据typeId返回号型名称
    @Override
    public List<String> getByTypeIds(QueryEquipmentSizeReq req) {
        List<String> typeIdsList = req.getTypeIdsList();
        List<String> idsList = selectByTypeIds(typeIdsList);
        return equipmentSizeMapper.searchByTypeIds(idsList);
    }

    @Override
    public List<SizeDto> alignSizeInfo(UpdateEquipmentSizeReq req) {
        String date = DateTimeUtil.TimeLongToString(req.getUpdateTime());
        return equipmentSizeMapper.alignSizeInfo(date);
    }


    public List<String> selectByTypeIds(List<String> typeIdsList){
        List<String> list1=new ArrayList<>();
        List<String> list2=new ArrayList<>();
        List<String> list3=new ArrayList<>();
        List<String> list4=new ArrayList<>();
        List<EquipmentType> list = equipmentTypeService.list(new LambdaQueryWrapper<EquipmentType>().in(EquipmentType::getId, typeIdsList));

        for (EquipmentType equipmentType:list) {
            //根据parentId判断他在第几层
            String parentIds = equipmentType.getParentIds();
            List<String> parentIdsList = Arrays.asList(parentIds.split(","));
            //判断parentIdsList的长度，将他放在第几层的位置
            if (parentIdsList.size()==1){
                list1.add(equipmentType.getId());
            } else if (parentIdsList.size()==2) {
                list2.add(equipmentType.getId());
            } else if (parentIdsList.size()==3) {
                list3.add(equipmentType.getId());
            }else {
                list4.add(equipmentType.getId());
            }

        }
        return equipmentTypeMapper.selectByItems(list1,list2,list3,list4);
    }

    private EquipmentSize querySize(UpdateEquipmentSizeReq req) {
        EquipmentSize app = this.getById(req.getId());

        if (ObjectUtil.isNull(app)) {
            throw new ServiceException(ProductExceptionEnum.SIZE_NOT_EXIST);
        }
        return app;
    }

    private LambdaQueryWrapper<EquipmentSize> createWrapper(QueryEquipmentSizeReq req) {
        LambdaQueryWrapper<EquipmentSize> wrapper = new LambdaQueryWrapper<>();
        if (ObjectUtil.isEmpty(req)) {
            return wrapper;
        }
        //根据业务编码查询
        wrapper.like(ObjectUtil.isNotEmpty(req.getTypeId()), EquipmentSize::getTypeId, req.getTypeId());
        //根据名称模糊查询
        wrapper.like(ObjectUtil.isNotEmpty(req.getName()), EquipmentSize::getName, req.getName());

//        wrapper.orderByAsc(EquipmentSize::getCode);
        return wrapper;
    }



}