package com.ruoyi.demo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.demo.config.MtStarProperties;
import com.ruoyi.demo.entity.*;
import com.ruoyi.demo.entity.bo.EquipmentBo;
import com.ruoyi.demo.entity.bo.PlanBo;
import com.ruoyi.demo.entity.bo.PlanItemBo;
import com.ruoyi.demo.entity.vo.EquipmentVo;
import com.ruoyi.demo.entity.vo.PlanItemVo;
import com.ruoyi.demo.enums.EquipmentStateEnum;
import com.ruoyi.demo.mapper.*;
import com.ruoyi.demo.service.EquipmentService;
import com.ruoyi.demo.utils.InitMapUtil;
import com.ruoyi.demo.utils.MtStarUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Service
@Transactional
public class EquipmentServiceImpl implements EquipmentService {
    @Autowired
    EquipmentMapper equipmentMapper;
    @Autowired
    InitMapUtil initMapUtil;

    @Autowired
    PlanItemMapper planItemMapper;

    @Autowired
    PlanMapper planMapper;

    @Autowired
    StatisticsMapper statisticsMapper;

    @Autowired
    DlUserMapper dlUserMapper;

    @Autowired
    PlanPushStatisticsMapper planPushStatisticsMapper;


    @Autowired
    @Qualifier("equipmentStateMap")
    HashMap<Integer,String> equipmentStateMap;

    @Autowired
    @Qualifier("equipmentOnStateMap")
    HashMap<Integer,String> equipmentOnStateMap;

    @Autowired
    MtStarUtil mtStarUtil;


    @Override
    public Integer addEquipment(EquipmentVo equipmentVo) {
        //判断是否已经存在设备Code
        QueryWrapper<Equipment> equipmentCode = new QueryWrapper<>();
        equipmentCode.eq("equipment_code", equipmentVo.getEquipmentCode());
        Long aLong = equipmentMapper.selectCount(equipmentCode);

        if (aLong == 0){
            Equipment equipment = new Equipment(equipmentVo);
            //1.新增地区码映射
            equipment.setAddrCodeInfo(initMapUtil.getInitAddrCodeMap(equipment.getAddrCode()));
            //2.新增创建时间
            equipment.setEnterTime(LocalDateTime.now(ZoneId.of("Asia/Shanghai")));

            if (equipmentVo.getOnState() == 1){
                //唤醒
                mtStarUtil.wakeup(equipmentVo.getEquipmentCode());
            }else {
                //休眠
                mtStarUtil.dormancy(equipmentVo.getEquipmentCode());
            }
            return equipmentMapper.insert(equipment);
        }
        return 0;
    }

    @Override
    public R updateEquipment(EquipmentVo equipmentVo) {
        QueryWrapper<Equipment> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("equipment_name","equipment_code","addr_info","addr_code","addr_code_info","on_state");
        queryWrapper.eq("equipment_id",equipmentVo.getEquipmentId());
        Equipment equipment = equipmentMapper.selectOne(queryWrapper);

        if (equipment != null){
            if (!equipmentVo.getAddrCode().equals(equipment.getAddrCode()))
                equipmentVo.setAddrCodeInfo(initMapUtil.getInitAddrCodeMap(equipmentVo.getAddrCode()));  //更新地区码映射

            String state = "";
            if (equipmentVo.getOnState() != equipment.getOnState()){
                if (equipmentVo.getOnState() == 1){
                    //唤醒
                    state = mtStarUtil.wakeup(equipmentVo.getEquipmentCode());
                }else {
                    //休眠
                    state = mtStarUtil.dormancy(equipmentVo.getEquipmentCode());
                }
            }

            //2.更新时间
            equipmentVo.setUpdateTime(LocalDateTime.now(ZoneId.of("Asia/Shanghai")));
            UpdateWrapper<Equipment> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("equipment_id",equipmentVo.getEquipmentId());
            updateWrapper.set("equipment_name",equipmentVo.getEquipmentName())
                .set("equipment_code",equipmentVo.getEquipmentCode())
                .set("annotation",equipmentVo.getAnnotation())
                .set("addr_info",equipmentVo.getAddrInfo())
                .set("addr_code",equipmentVo.getAddrCode())
                .set("addr_code_info",equipmentVo.getAddrCode())
                .set("state",equipmentVo.getState())
                .set("on_state",equipmentVo.getOnState())
                .set("lat",equipmentVo.getLat())
                .set("lng",equipmentVo.getLng())
                .set("manufacturers",equipmentVo.getManufacturers())
                .set("maintain_name",equipmentVo.getMaintainName())
                .set("maintain_telephone",equipmentVo.getMaintainTelephone())
                .set("update_time",equipmentVo.getUpdateTime());
            equipmentMapper.update(null,updateWrapper);
            //修改冗余字段
            if (!equipment.getEquipmentName().equals(equipmentVo.getEquipmentName()) || !equipment.getEquipmentCode().equals(equipmentVo.getEquipmentCode()) || !equipment.getAddrCode().equals(equipmentVo.getAddrCode())){
                UpdateWrapper<PlanItem> updateWrapper1 = new UpdateWrapper<>();
                updateWrapper1.eq("equipment_id",equipmentVo.getEquipmentId());
                updateWrapper1.set("equipment_name",equipmentVo.getEquipmentName())
                    .set("equipment_code",equipmentVo.getEquipmentCode())
                    .set("addr_info",equipmentVo.getAddrInfo())
                    .set("addr_code",equipmentVo.getAddrCode())
                    .set("addr_code_info",equipmentVo.getAddrCode());
                planItemMapper.update(null,updateWrapper1);
            }


            if (!equipment.getEquipmentName().equals(equipmentVo.getEquipmentName()) || !equipment.getEquipmentCode().equals(equipmentVo.getEquipmentCode())){
                UpdateWrapper<Statistics> updateWrapper2 = new UpdateWrapper<>();
                updateWrapper2.eq("equipment_id",equipmentVo.getEquipmentId());
                updateWrapper2.set("equipment_name",equipmentVo.getEquipmentName())
                    .set("equipment_code",equipmentVo.getEquipmentCode());
                statisticsMapper.update(null,updateWrapper2);

                UpdateWrapper<DlUser> updateWrapper3 = new UpdateWrapper<>();
                updateWrapper3.eq("start_equipment_id",equipmentVo.getEquipmentId());
                updateWrapper3.set("start_equipment_name",equipmentVo.getEquipmentName())
                    .set("start_equipment_code",equipmentVo.getEquipmentCode());
                dlUserMapper.update(null,updateWrapper3);

                UpdateWrapper<DlUser> updateWrapper4 = new UpdateWrapper<>();
                updateWrapper4.eq("end_equipment_id",equipmentVo.getEquipmentId());
                updateWrapper4.set("end_equipment_name",equipmentVo.getEquipmentName())
                    .set("end_equipment_code",equipmentVo.getEquipmentCode());
                dlUserMapper.update(null,updateWrapper4);

                UpdateWrapper<PlanPushStatistics> updateWrapper5 = new UpdateWrapper<>();
                updateWrapper5.eq("equipment_id",equipmentVo.getEquipmentId());
                updateWrapper5.set("equipment_name",equipmentVo.getEquipmentName())
                    .set("equipment_code",equipmentVo.getEquipmentCode());
                planPushStatisticsMapper.update(null,updateWrapper5);
            }

            return R.ok("修改成功,"+state);
        }else {
            return R.fail("设备不存在");
        }


    }

    @Override
    public EquipmentBo getEquipment(String equipmentId) {
        Equipment equipment = equipmentMapper.selectById(equipmentId);
        EquipmentBo equipmentBo = new EquipmentBo(equipment);
        return equipmentBo;
    }

    /*
    * TODO 需要考虑上面有没有广告
    * */
    @Override
    public String deleteEquipment(String[] equipmentIds) {
        //1.查询设备下身份有广告
        QueryWrapper<PlanItemBo> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("equipment_id",equipmentIds);
        queryWrapper.and(planItemBoQueryWrapper -> {
            planItemBoQueryWrapper.eq("dl_plan_item.deleted",0);
        });
        queryWrapper.and(planItemBoQueryWrapper -> {
            planItemBoQueryWrapper.gt("plan_end_time",LocalDateTime.now(ZoneId.of("Asia/Shanghai")));
        });
        Integer count = planItemMapper.getEuipmentPlanCont(queryWrapper);
        if (count > 0)
            return "设备下存在广告计划，请移除广告后在删除设备";
        equipmentMapper.deleteBatchIds(Arrays.asList(equipmentIds));
        return "移除成功";
    }



    @Override
    public Page<Equipment> getEquipmentBySelect(EquipmentVo equipmentVo) {
        QueryWrapper<Equipment> queryWrapper = new QueryWrapper<>();
        queryWrapper.isNull("store_id");
        if (equipmentVo.getSearchText() != null && !equipmentVo.getSearchText().equals("")){
            queryWrapper.and(queryWrapper1 -> {
                queryWrapper1.likeRight("equipment_id",equipmentVo.getSearchText());
                queryWrapper1.or().like("equipment_name",equipmentVo.getSearchText());
                queryWrapper1.or().like("equipment_code",equipmentVo.getSearchText());
            });
        }

        Page<Equipment> page = new Page<>();
        page.setCurrent(equipmentVo.getPageNum());
        page.setSize(equipmentVo.getPageSize());
        Page<Equipment> pageInfo = equipmentMapper.selectPage(page, queryWrapper);
        return pageInfo;
    }

    @Override
    public void addStoreEquipment(EquipmentVo equipmentVo) {
        UpdateWrapper<Equipment> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("equipment_id",equipmentVo.getEquipmentId());
        updateWrapper.set("store_id",equipmentVo.getStoreId());
        equipmentMapper.update(null,updateWrapper);
    }

    @Override
    public Page<Equipment> getEquipmentByStoreId(EquipmentVo equipmentVo) {
        QueryWrapper<Equipment> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("store_id",equipmentVo.getStoreId());
        Page<Equipment> page = new Page<>();
        page.setCurrent(equipmentVo.getPageNum());
        page.setSize(equipmentVo.getPageSize());
        Page<Equipment> pageInfo = equipmentMapper.selectPage(page, queryWrapper);
        return pageInfo;
    }

    /**
     * TODO 待测试
     * @param equipmentVo
     * @return
     */
    @Override
    public IPage<PlanItemBo> getEquipmentPlanList(EquipmentVo equipmentVo) {
        Page<PlanItemBo> page = new Page<>();
        page.setCurrent(equipmentVo.getPageNum());
        page.setSize(equipmentVo.getPageSize());

        QueryWrapper<PlanItemBo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("equipment_id",equipmentVo.getEquipmentId());
        queryWrapper.and(planItemBoQueryWrapper -> {
            planItemBoQueryWrapper.eq("dl_plan_item.deleted",0);
        });
        queryWrapper.and(planItemBoQueryWrapper -> {
            planItemBoQueryWrapper.eq("dl_plan.state",1);
        });
        queryWrapper.and(planItemBoQueryWrapper -> {
            planItemBoQueryWrapper.eq("dl_plan.on_state",1);
        });
        queryWrapper.and(planItemBoQueryWrapper -> {
            planItemBoQueryWrapper.gt("plan_end_time",LocalDateTime.now(ZoneId.of("Asia/Shanghai")));
        });

        queryWrapper.apply("dl_plan.`plan_id` = dl_plan_item.`plan_id`");
        if (equipmentVo.getSearchText() != null && !equipmentVo.getSearchText().equals("")){
            queryWrapper.and(planItemBoQueryWrapper -> {
                planItemBoQueryWrapper.likeRight("plan_id",equipmentVo.getSearchText()).or()
                    .like("plan_name",equipmentVo.getSearchText());
            });
        }
        queryWrapper.orderByDesc("sort");
        IPage<PlanItemBo> euipmentPlanList = planItemMapper.getEuipmentPlanList(page, queryWrapper);

        return euipmentPlanList;
    }

    @Override
    public void updateEquipmentPlan(PlanItemVo planItemVo) {
        UpdateWrapper<PlanItem> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("item_id",planItemVo.getItemId());
        updateWrapper.set("sort",planItemVo.getSort());
        planItemMapper.update(null,updateWrapper);
    }

    @Override
    public HashMap getEquipmentCount() {
        QueryWrapper<Equipment> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("state","count(*) as onState");
        queryWrapper.groupBy("state");
        List<Equipment> equipment = equipmentMapper.selectList(queryWrapper);
        HashMap<String, Integer> objectObjectHashMap = new HashMap<>();
        int total = 0;
        for (Equipment equipment1 : equipment) {
            objectObjectHashMap.put(String.valueOf(equipment1.getState()),equipment1.getOnState());
            total+=equipment1.getOnState();
        }
        objectObjectHashMap.put("total",total);
        return objectObjectHashMap;
    }

    @Override
    public HashMap getEquipmentList(EquipmentVo equipmentVo) {
        QueryWrapper<Equipment> queryWrapper = new QueryWrapper<>();
        if (equipmentVo.getSearchText() != null && !equipmentVo.getSearchText().equals("")){
            queryWrapper.likeRight("equipment_id",equipmentVo.getSearchText());
            queryWrapper.or().like("equipment_name",equipmentVo.getSearchText());
            queryWrapper.or().like("equipment_code",equipmentVo.getSearchText());
            queryWrapper.or().like("maintain_name",equipmentVo.getSearchText());
            queryWrapper.or().likeRight("maintain_telephone",equipmentVo.getSearchText());
        }

        if (equipmentVo.getState() != null){
            queryWrapper.and(equipmentQueryWrapper -> {
                equipmentQueryWrapper.eq("state",equipmentVo.getState());
            });
        }

        if (equipmentVo.getOnState() != null){
            queryWrapper.and(equipmentQueryWrapper -> {
                equipmentQueryWrapper.eq("on_state",equipmentVo.getOnState());
            });
        }

        //查询设备
        Page<Equipment> page = new Page();
        page.setCurrent(equipmentVo.getPageNum());
        page.setSize(equipmentVo.getPageSize());
        Page<Equipment> equipmentPage = equipmentMapper.selectPage(page, queryWrapper);

        //查询广告数
        List<String> collect = equipmentPage.getRecords().stream().map(item -> {
            return item.getEquipmentId();
        }).collect(Collectors.toList());

        HashMap<String, Integer> hashMap = new HashMap<>();
        List<EquipmentBo> result = new ArrayList<>();
        if(!collect.isEmpty()){
            QueryWrapper<PlanItem> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.select("equipment_id","count(*) as sort");
            queryWrapper1.in("equipment_id",collect);
            queryWrapper1.groupBy("equipment_id");
            List<PlanItem> planItems = planItemMapper.selectList(queryWrapper1);
            for (PlanItem planItem : planItems) {
                hashMap.put(planItem.getEquipmentId(),planItem.getSort());
            }

            //组装
            for (Equipment equipment1 : equipmentPage.getRecords()) {
                EquipmentBo equipmentBo = new EquipmentBo(equipment1);
                Integer integer = hashMap.get(equipmentBo.getEquipmentId());
                if (integer == null){
                    equipmentBo.setPlanCounnt(0);
                }else {
                    equipmentBo.setPlanCounnt(integer);
                }
                result.add(equipmentBo);
            }
        }


        HashMap<String, Object> objectObjectHashMap = new HashMap<>();
        equipmentPage.setRecords(null);
        objectObjectHashMap.put("page",equipmentPage);
        objectObjectHashMap.put("data",result);
        return objectObjectHashMap;
    }

    @Override
    public void deleteStoreEquipment(String[] equipmentIds) {
        UpdateWrapper<Equipment> updateWrapper = new UpdateWrapper<>();
        updateWrapper.in("equipment_id",equipmentIds);
        updateWrapper.set("store_id",null);
        equipmentMapper.update(null,updateWrapper);
    }

    @Override
    public void deleteEquipmentPlan(String[] planItemIds) {
        planItemMapper.deleteBatchIds(Arrays.asList(planItemIds));
    }


}
