package com.yuchen.saas.park.service.fault.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.thinkunion.park.service.common.cache.CacheNames;
import com.yuchen.saas.park.api.entity.fault.EquipmentBreakdownHistory;
import com.yuchen.saas.park.api.entity.fault.EquipmentBreakdownRule;
import com.yuchen.saas.park.api.entity.fault.EquipmentBreakdownType;
import com.yuchen.saas.park.api.entity.fault.EquipmentPictureRule;
import com.yuchen.saas.park.api.entity.park.PmgBatParkInfo;
import com.yuchen.saas.park.api.vo.fault.EquipmentBreakdownTypeVo;
import com.yuchen.saas.park.api.vo.fault.EquipmentStatusVo;
import com.yuchen.saas.park.service.fault.mapper.EquipmentBreakdownTypeMapper;
import com.yuchen.saas.park.service.fault.service.EquipmentBreakdownRuleService;
import com.yuchen.saas.park.service.fault.service.EquipmentBreakdownTypeService;
import com.yuchen.saas.park.service.fault.service.EquipmentPictureRuleService;
import com.yuchen.saas.park.service.fault.service.EquipmentStatusService;
import com.yuchen.saas.park.service.service.PmgBatParkInfoService;
import org.nest.springwrap.core.mp.base.BaseServiceImpl;
import org.nest.springwrap.core.mp.support.Condition;
import org.nest.springwrap.core.redis.cache.NestRedis;
import org.nest.springwrap.core.tool.api.R;
import org.nest.springwrap.core.tool.utils.BeanUtil;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @Author: 肖润飞
 * @CreateTime: 2022/10/18 15:43
 * @Description: 设备故障类型
 * @Version: 1.0
 */
@Service
public class EquipmentBreakdownTypeServiceImpl extends BaseServiceImpl<EquipmentBreakdownTypeMapper, EquipmentBreakdownType> implements EquipmentBreakdownTypeService {

    @Resource
    @Lazy
    private EquipmentStatusService statusService;

    @Resource
    @Lazy
    private EquipmentPictureRuleService pictureRuleService;

    @Resource
    @Lazy
    private EquipmentBreakdownRuleService ruleService;

    @Resource
    private PmgBatParkInfoService pmgBatParkInfoService;

    @Resource
    private NestRedis nestRedis;

    @Override
    public R isShow(List<EquipmentBreakdownType> types) {

        StringBuilder sb = new StringBuilder();
        types.forEach(r -> {
            sb.append(r.getId()).append(",");
        });
        String ids = sb.toString();
        // 查询全部的
        List<EquipmentBreakdownType> list = this.list();
        for (EquipmentBreakdownType pictureType : list) {
            if (ids.contains(pictureType.getId().toString())) {
                pictureType.setIsShow(1);
            } else {
                pictureType.setIsShow(0);
            }
        }
        this.updateBatchById(list);
        return R.status(true);
    }


    /**
     * 获得设备故障类型ListVo
     *
     * @return
     */
    @Override
    public R listVo() {
        List<EquipmentBreakdownType> list = this.list();
        List<EquipmentBreakdownTypeVo> resultList = new ArrayList<>(list.size());
        LambdaQueryWrapper<EquipmentBreakdownHistory> query = Wrappers.lambdaQuery();
        list.forEach(type -> {
            EquipmentBreakdownTypeVo vo = new EquipmentBreakdownTypeVo();
            BeanUtil.copyProperties(type, vo);
            query.clear();
            List<PmgBatParkInfo> allPark = pmgBatParkInfoService.getAllPark();
            AtomicLong total = new AtomicLong();
            allPark.forEach(park -> {
                EquipmentStatusVo statusVo = new EquipmentStatusVo();
                statusVo.setParkId(park.getId());
                statusVo.setBreakdownCode(type.getBreakdownCode());
                statusVo.setStatus(1);
                R result = statusService.pageStatus(new Page(), statusVo);
                IPage<EquipmentStatusVo> data = (IPage<EquipmentStatusVo>) result.getData();
                total.getAndAdd(data.getTotal());
            });
            vo.setTotalNumber(total.longValue());
            resultList.add(vo);
        });
        return R.data(resultList);
    }

    /**
     * 分页vo
     *
     * @param page
     * @param type
     * @return
     */
    @Override
    public R pageVo(Page page, EquipmentBreakdownType type) {
        Page res = this.page(page, Condition.getQueryWrapper(type));
        List<EquipmentBreakdownType> records = res.getRecords();
        List<EquipmentBreakdownTypeVo> voList = new ArrayList<>(records.size());
        res.setRecords(voList);
        LambdaQueryWrapper<EquipmentPictureRule> query = Wrappers.lambdaQuery();
        for (EquipmentBreakdownType record : records) {
            EquipmentBreakdownTypeVo vo = new EquipmentBreakdownTypeVo();
            BeanUtil.copyProperties(record, vo);
            query.clear();
            String pictureCode = record.getPictureCode();
            if (StrUtil.isNotBlank(pictureCode)) {
                query.eq(EquipmentPictureRule::getPictureCode, pictureCode).last(" limit 1");
                EquipmentPictureRule pictureRule = pictureRuleService.getOne(query);
                vo.setPictureName(pictureRule.getPictureName());
            }
            voList.add(vo);
        }
        return R.data(res);
    }

    /**
     * @param type
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public R updateType(EquipmentBreakdownType type) {
        EquipmentBreakdownType oldType = this.getById(type.getId());
        if (!oldType.getBreakdownCode().equals(type.getBreakdownCode()) && !StrUtil.isBlank(type.getPictureCode())) {
            //说明更改了code
            LambdaQueryWrapper<EquipmentBreakdownType> query = Wrappers.lambdaQuery();
            query.eq(EquipmentBreakdownType::getBreakdownCode, type.getBreakdownCode())
                    .ne(EquipmentBreakdownType::getId, type.getId());
            int count = this.count(query);
            if (count > 0) {
                return R.error("已经存在相同的BreakdownCode标签");
            }
            //更新 rule中的code
            LambdaUpdateWrapper<EquipmentBreakdownRule> updateRuleQuery = Wrappers.lambdaUpdate();
            EquipmentBreakdownRule rule = new EquipmentBreakdownRule();
            rule.setBreakdownCode(type.getBreakdownCode());
            updateRuleQuery.eq(EquipmentBreakdownRule::getBreakdownCode, oldType.getBreakdownCode());
            boolean update = ruleService.update(rule, updateRuleQuery);
            if (update) {
                // 更新规则type缓存
                nestRedis.hSet(CacheNames.EQ_BREAKDOWN_TYPE, type.getBreakdownCode(), type);
                // 删除故障规则缓存
                nestRedis.del(CacheNames.EQ_BREAKDOWN_RULE_KEY);
            }
        }
        this.updateById(type);
        return R.data(true);
    }

    @Override
    public R deleteType(EquipmentBreakdownType type) {
        // 删除当前
        EquipmentBreakdownType deleteType = this.getById(type.getId());
        // 判断当前是否有故障规则使用
        LambdaQueryWrapper<EquipmentBreakdownRule> query = Wrappers.lambdaQuery();
        query.eq(EquipmentBreakdownRule::getBreakdownCode, deleteType.getBreakdownCode());
        int count = ruleService.count(query);
        if (count > 0) {
            return R.error("该故障标签被的故障规则使用,不能删除");
        }
        this.removeById(type);
        // 删除故障类型缓存
        nestRedis.hDel(CacheNames.EQ_BREAKDOWN_TYPE, type.getBreakdownCode());
        // 删除故障规则缓存
        nestRedis.del(CacheNames.EQ_BREAKDOWN_RULE_KEY);
        return R.data(true);
    }
}