package com.xy.job;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.xy.collections.list.JArrayList;
import com.xy.collections.list.JList;
import com.xy.collections.map.JMap;
import com.xy.dto.MercAccountDto;
import com.xy.dto.MercArrearageConfigDto;
import com.xy.dto.be.MercDto;
import com.xy.entity.DeviceAlgorithmCharging;
import com.xy.entity.DeviceInfo;
import com.xy.service.DeviceAlgorithmChargingServiceImpl;
import com.xy.service.DeviceInfoServiceImpl;
import com.xy.service.MercAccountService;
import com.xy.service.MercArrearageConfigService;
import com.xy.service.be.MercService;
import com.xy.sys.EnumMercCostMsgConfig;
import com.xy.utils.Emptys;
import com.xy.utils.SysDictUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 设备算法费job
 */
@Slf4j
@Component
@AllArgsConstructor
public class DeviceAlgorithmChargingJob {

    private MercService mercService;

    private MercAccountService mercAccountService;

    private DeviceInfoServiceImpl deviceInfoService;

    private DeviceAlgorithmChargingServiceImpl deviceAlgorithmChargingService;

    private MercArrearageConfigService mercArrearageConfigService;

    /**
     * 算法费设备停机
     *
     * @return
     */
    @XxlJob("deviceAlgorithmChargingHalt")
    public ReturnT<String> deviceAlgorithmChargingHalt() {
        //查询余额<=0商户
        List<MercAccountDto.Vo> list = mercAccountService.list(new MercAccountDto.SelectList().setEndBalance(0)).getData();
        if (!Emptys.check(list)) {
            return ReturnT.SUCCESS;
        }
        //筛选商户欠费天数
        int day = SysDictUtils.getValue(EnumMercCostMsgConfig.Code.CODE.getCode(), EnumMercCostMsgConfig.ARREARAGE_DAY.getCode(), Integer.class);
        JList<MercAccountDto.Vo> mercAccounts = new JArrayList<>(list).filter().ge(MercAccountDto.Vo::getArrearageDay, day).list();
        if (!Emptys.check(mercAccounts)) {
            return ReturnT.SUCCESS;
        }
        //查询白名单
        MercArrearageConfigDto.SelectList selectList = new MercArrearageConfigDto.SelectList();
        selectList.setType(2);
        List<MercArrearageConfigDto.Vo> data = mercArrearageConfigService.list(selectList).getData();
        JMap<Long, MercArrearageConfigDto.Vo> mercArrearageConfigJMaps = new JArrayList<>(data).toMap(MercArrearageConfigDto.Vo::getMercId).cover();
        //查询是否提现模式
        Map<Long, Boolean> isDrawMaps = mercService.isDrawList(new MercDto.IsDrawList().setMercIds(new JArrayList<>(list).getProperty(MercAccountDto.Vo::getMercId))).getData();
        //循环处理
        mercAccounts.forEach(vo -> {
            //验证白名单
            MercArrearageConfigDto.Vo mercArrearageConfig = mercArrearageConfigJMaps.get(vo.getMercId());
            if (Emptys.check(mercArrearageConfig)) {
                if (vo.getArrearageDay() < mercArrearageConfig.getArrearageDay()) {
                    return;
                }
            }
            //验证是否提现模式
            Boolean isDraw = isDrawMaps.get(vo.getMercId());
            if (isDraw) {
                return;
            }
            //查询商户未冻结设备
            List<DeviceInfo> deviceInfos = deviceInfoService.list(new LambdaQueryWrapper<DeviceInfo>()
                    .in(DeviceInfo::getDeviceType, Arrays.asList(1, 2))
                    .eq(DeviceInfo::getMercId, vo.getMercId())
                    .eq(DeviceInfo::getActiveState, 1)
                    .eq(DeviceInfo::getFreezeStatus, 1)
            );
            if (!Emptys.check(deviceInfos)) {
                return;
            }
            JMap<Long, DeviceInfo> deviceInfosJMaps = new JArrayList<>(deviceInfos).toMap(DeviceInfo::getDeviceId).cover();
            //分组统计设备可用算法卡包
            String algorithmDate = DateUtil.format(DateUtil.date(), DatePattern.PURE_DATE_PATTERN);
            LambdaQueryWrapper<DeviceAlgorithmCharging> lambdaQueryWrapper = new LambdaQueryWrapper<DeviceAlgorithmCharging>()
                    .select(DeviceAlgorithmCharging::getDeviceId)
                    .eq(DeviceAlgorithmCharging::getMercId, vo.getMercId())
                    .gt(DeviceAlgorithmCharging::getUnusedSize, 0)
                    .in(DeviceAlgorithmCharging::getDeviceId, deviceInfosJMaps.getKeys())
                    .and(deviceAlgorithmChargingLambdaQueryWrapper -> deviceAlgorithmChargingLambdaQueryWrapper
                            .eq(DeviceAlgorithmCharging::getTimeout, -1)
                            .or(deviceAlgorithmChargingLambdaQueryWrapper1 -> deviceAlgorithmChargingLambdaQueryWrapper1
                                    .le(DeviceAlgorithmCharging::getBeginTime, Integer.valueOf(algorithmDate))
                                    .ge(DeviceAlgorithmCharging::getTimeout, Integer.valueOf(algorithmDate))
                            )
                    )
                    .groupBy(DeviceAlgorithmCharging::getDeviceId);
            List<DeviceAlgorithmCharging> deviceAlgorithmChargings = deviceAlgorithmChargingService.list(lambdaQueryWrapper);
            JMap<Long, DeviceAlgorithmCharging> deviceAlgorithmChargingsJMaps = new JArrayList<>(deviceAlgorithmChargings).toMap(DeviceAlgorithmCharging::getDeviceId).cover();
            //判断是否过期
            List<DeviceInfo> updateDeviceInfos = new ArrayList<>();
            LocalDateTime now = LocalDateTime.now();
            deviceInfosJMaps.forEach((deviceId, deviceInfo) -> {
                if (deviceAlgorithmChargingsJMaps.containsKey(deviceId)) {
                    return;
                }
                //冻结设备
                DeviceInfo updateDeviceInfo = new DeviceInfo()
                        .setDeviceId(deviceId)
                        .setFreezeStatus(2)
                        .setUpdateTime(now);
                updateDeviceInfos.add(updateDeviceInfo);
            });
            if (Emptys.check(updateDeviceInfos)) {
                deviceInfoService.updateBatchById(updateDeviceInfos);
            }
        });
        return ReturnT.SUCCESS;
    }
}
