package com.xy.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xy.dto.DeviceEventMsgDto;
import com.xy.dto.DeviceInfoDto;
import com.xy.entity.DeviceEventMsg;
import com.xy.entity.SysCodeConfigureRedis;
import com.xy.mapper.DeviceEventMsgMapper;
import com.xy.service.factory.device.DeviceFactory;
import com.xy.utils.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import javax.validation.constraints.NotEmpty;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.xy.utils.Beans.copy;
import static com.xy.utils.PlusBeans.toIPage;
import static com.xy.utils.PlusBeans.toPageBean;

/**
 * <p>
 * 机器-消息表 服务实现类
 * </p>
 *
 * @author lijin
 * @since 2023-01-09
 */
@Service
@Api(tags = "机器-消息表")
@AllArgsConstructor(onConstructor_ = @Lazy)
public class DeviceEventMsgServiceImpl extends ServiceImpl<DeviceEventMsgMapper, DeviceEventMsg> implements DeviceEventMsgService {

    private DeviceInfoServiceImpl deviceInfoService;

    @Override
    @ApiOperation("添加")
    public R save(DeviceEventMsgDto.Save save) {
        DeviceInfoDto.Vo deviceInfo = deviceInfoService.obj(new DeviceInfoDto.Obj().setDeviceId(save.getDeviceId())).getData();
        if (deviceInfo == null) {
            return R.fail("设备不存在");
        }
        return FactoryUtils.getServiceRoute(DeviceFactory.class, deviceInfo.getDeviceType()).eventMsg(save);
    }

    @Override
    @ApiOperation("分页查询")
    public R<PageBean<DeviceEventMsgDto.Vo>> page(@RequestBody DeviceEventMsgDto.Page page) {
        Map<String, SysCodeConfigureRedis> stringSysCodeConfigureRedisMap = SysCodeConfigureUtils.all();
        List<String> codes = new ArrayList<>();
        if (Emptys.check(page.getCode())) {
            codes = sonCodes(page.getCode(), stringSysCodeConfigureRedisMap);
            codes.add(page.getCode());
        }
        PageBean pageBean = page.getPage();
        LambdaQueryWrapper<DeviceEventMsg> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(page, DeviceEventMsg.class)
                .ge(DeviceEventMsg::getCreateTime, page.getBeginCreateTime())
                .le(DeviceEventMsg::getCreateTime, page.getEndCreateTime())
                .in(DeviceEventMsg::getCode, codes)
                .like(DeviceEventMsg::getMsg)
                .build()
                .orderByDesc(!Emptys.check(pageBean.getOrders()), DeviceEventMsg::getId);
        IPage<DeviceEventMsg> iPage = page(toIPage(pageBean), lambdaQueryWrapper);
        PageBean<DeviceEventMsgDto.Vo> voPageBean = toPageBean(DeviceEventMsgDto.Vo.class, iPage);
        //反显设备名称
        if (Emptys.check(voPageBean.getRecords())) {
            List<Long> deviceIdList = voPageBean.getRecords().stream().map(DeviceEventMsgDto.Vo::getDeviceId).collect(Collectors.toList());
            Map<Long, String> deviceMap = deviceInfoService.getDeviceNameList(new DeviceInfoDto.DeviceIdDto().setDeviceId(deviceIdList)).getData();
            voPageBean.getRecords().forEach(i -> {
                i.setDeviceName(deviceMap.get(i.getDeviceId()));
                SysCodeConfigureRedis sysCodeConfigureRedis = stringSysCodeConfigureRedisMap.get(i.getCode());
                if (sysCodeConfigureRedis != null) {
                    i.setSysCodeConfigureRedis(sysCodeConfigureRedis);
                }
            });
        }
        return R.ok(voPageBean);
    }

    @PostMapping("list")
    @ApiOperation("集合查询")
    public R<List<DeviceEventMsgDto.Vo>> list(@RequestBody DeviceEventMsgDto.SelectList selectList) {
        Map<String, SysCodeConfigureRedis> stringSysCodeConfigureRedisMap = SysCodeConfigureUtils.all();
        List<String> codes = new ArrayList<>();
        if (Emptys.check(selectList.getCode())) {
            codes = sonCodes(selectList.getCode(), stringSysCodeConfigureRedisMap);
            codes.add(selectList.getCode());
        }
        LambdaQueryWrapper<DeviceEventMsg> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(selectList, DeviceEventMsg.class)
                .in(DeviceEventMsg::getId, selectList.getIds())
                .in(DeviceEventMsg::getDeviceId, selectList.getDeviceIds())
                .in(DeviceEventMsg::getCode, codes)
                .like(DeviceEventMsg::getMsg)
                .build();
        List<DeviceEventMsg> list = list(lambdaQueryWrapper);
        List<DeviceEventMsgDto.Vo> vos = copy(DeviceEventMsgDto.Vo.class, list);
        vos.forEach(vo -> {
            SysCodeConfigureRedis sysCodeConfigureRedis = stringSysCodeConfigureRedisMap.get(vo.getCode());
            if (sysCodeConfigureRedis != null) {
                vo.setSysCodeConfigureRedis(sysCodeConfigureRedis);
            }
        });
        return R.ok(vos);
    }

    @PostMapping("count")
    @ApiOperation("统计查询")
    public R<List<DeviceEventMsgDto.CountVo>> count(@RequestBody @Validated DeviceEventMsgDto.Count count) {
        List<String> codes = count.getCodes();
        List<DeviceEventMsgDto.CountVo> countVos = new ArrayList<>(codes.size());
        codes.forEach(code -> {
            LambdaQueryWrapper<DeviceEventMsg> queryWrapper = new LambdaQueryWrapper<DeviceEventMsg>()
                    .eq(DeviceEventMsg::getCode, code)
                    .ge(Emptys.check(count.getCreateTimeBegin()), DeviceEventMsg::getCreateTime, count.getCreateTimeBegin())
                    .le(Emptys.check(count.getCreateTimeEnd()), DeviceEventMsg::getCreateTime, count.getCreateTimeEnd());
            long countNum = count(queryWrapper);
            DeviceEventMsgDto.CountVo countVo = new DeviceEventMsgDto.CountVo()
                    .setCode(code)
                    .setCount(countNum);
            countVos.add(countVo);
        });
        return R.ok(countVos);
    }


    /**
     * 递归获取子编码
     *
     * @param code
     * @return
     */
    private List<String> sonCodes(String code, Map<String, SysCodeConfigureRedis> stringSysCodeConfigureRedisMap) {
        List<String> codes = new ArrayList<>();
        if (Emptys.check(code)) {
            stringSysCodeConfigureRedisMap.forEach((codeStr, sysCodeConfigureRedis) -> {
                if (!Emptys.check(sysCodeConfigureRedis.getPaterCode())) {
                    return;
                }
                if (sysCodeConfigureRedis.getPaterCode().equals(code)) {
                    codes.add(codeStr);
                    List<String> list = sonCodes(codeStr, stringSysCodeConfigureRedisMap);
                    if (Emptys.check(list)) {
                        codes.addAll(list);
                    }
                }
            });
        }
        return codes;
    }
}