package com.casic.missiles.service.Impl.equipment;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import com.alibaba.excel.util.DateUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.casic.missiles.core.model.auth.AuthUser;
import com.casic.missiles.core.shiro.ShiroKit;
import com.casic.missiles.dto.ReturnDTO;
import com.casic.missiles.dto.ReturnUtil;
import com.casic.missiles.dto.equipment.EquipmentWorkbenchResponse;
import com.casic.missiles.enums.system.ApplyFromIdEnum;
import com.casic.missiles.enums.BusinessExceptionEnum;
import com.casic.missiles.exception.BusinessException;
import com.casic.missiles.mapper.MeterFixedAssetsMapper;
import com.casic.missiles.mapper.equipment.EquipmentApplyEquipmentMapper;
import com.casic.missiles.mapper.equipment.EquipmentStandardEquipmentMapper;
import com.casic.missiles.mapper.equipment.EquipmentWorkbenchMapper;
import com.casic.missiles.model.equipment.EquipmentApplyEquipment;
import com.casic.missiles.model.equipment.EquipmentFixedAssets;
import com.casic.missiles.model.equipment.EquipmentStandardEquipment;
import com.casic.missiles.model.system.SystemFlowForm;
import com.casic.missiles.service.equipment.IEquipmentWorkbenchService;
import com.casic.missiles.service.system.ISystemFlowFormService;
import org.flowable.engine.HistoryService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service("IEquipmentWorkbenchService")
public class EquipmentWorkbenchServiceImpl implements IEquipmentWorkbenchService {

    @Resource
    private EquipmentWorkbenchMapper equipmentWorkbenchMapper;

    @Resource
    private MeterFixedAssetsMapper meterFixedAssetsMapper;

    @Resource
    private EquipmentApplyEquipmentMapper equipmentMapper;

    @Resource
    private EquipmentStandardEquipmentMapper meterStandardEquipmentMapper;

    @Resource
    private ISystemFlowFormService flowFormService;

    @Resource
    private HistoryService historyService;

    @Override
    public ReturnDTO<EquipmentWorkbenchResponse> dataStatistics() {

        EquipmentWorkbenchResponse response = new EquipmentWorkbenchResponse();
        List<HashMap<String,Object>> measureStateList = new ArrayList<>();
        List<HashMap<String,Object>> standardStateList = new ArrayList<>();
        List<HashMap<String,Object>> equipmentApplyList = new ArrayList<>();
        // 测量设备闲置
        measureStateList.add(getApplyCount("闲置设备", ApplyFromIdEnum.DEVICE_UNUSED_APPROVAL.getCode()));
        // 测量设备封存
        measureStateList.add(getApplyCount("封存设备", ApplyFromIdEnum.DEVICE_SEALED_APPROVAL.getCode()));
        // 标准装置暂停
        standardStateList.add(getApplyCount("暂停装置", ApplyFromIdEnum.STANDARD_PAUSE_APPROVAL.getCode()));
        // 标准装置撤销
        standardStateList.add(getApplyCount("撤销装置", ApplyFromIdEnum.STANDARD_REVERT_APPROVAL.getCode()));
        // 设备借用
        equipmentApplyList.add(getApplyCount("本月设备借用", ApplyFromIdEnum.DEVICE_BORROW_APPROVAL.getCode()));
        // 设备领用
        equipmentApplyList.add(getApplyCount("本月设备领用", ApplyFromIdEnum.DEVICE_CONSUMING_APPROVAL.getCode()));
        // 测量设备总数
        QueryWrapper<EquipmentFixedAssets> wrapper = new QueryWrapper<>();
        wrapper.eq("asset_type", "1");
        response.setMeasureSum(String.valueOf(meterFixedAssetsMapper.selectCount(wrapper)));
        // 测量设备在用
        wrapper.eq("manager_state", "1");
        HashMap<String,Object> map = new HashMap<>();
        map.put("state","在用设备");
        map.put("count",meterFixedAssetsMapper.selectCount(wrapper));
        measureStateList.add(map);
        // 标准装置总数
        QueryWrapper<EquipmentStandardEquipment> standardEquipmentQueryWrapper = new QueryWrapper<>();
        response.setStandardSum(String.valueOf(meterStandardEquipmentMapper.selectCount(standardEquipmentQueryWrapper)));
        // 测量设备在用
        standardEquipmentQueryWrapper.eq("manager_state", "1");
        map = new HashMap<>();
        map.put("state","在用装置");
        map.put("count",meterStandardEquipmentMapper.selectCount(standardEquipmentQueryWrapper));
        standardStateList.add(map);
        response.setMeasureStateList(measureStateList);
        response.setStandardStateList(standardStateList);
        response.setEquipmentApplyList(equipmentApplyList);
        return ReturnUtil.success(response);
    }


    private HashMap<String,Object> getApplyCount(String state,String fromId){
        Long count = 0L;
        List<String> businessKeys = getPassedList(getProcDefId(fromId));
        QueryWrapper<EquipmentApplyEquipment> queryWrapper = new QueryWrapper<>();
        if(businessKeys.size()!=0){
            queryWrapper.in("apply_id",businessKeys);
            count = equipmentMapper.selectCount(queryWrapper);
        }
        HashMap<String,Object> hashMap = new HashMap<>();
        hashMap.put("state",state);
        hashMap.put("count",count);
        return hashMap;
    }

    private String getProcDefId(String formId){
        //根据业务表单id获取流程定义
        QueryWrapper<SystemFlowForm> wrapper = new QueryWrapper<>();
        wrapper.eq("form_id", formId);
        SystemFlowForm flowForm = flowFormService.getOne(wrapper);
        return flowForm.getProcDefId();
    }

    // 通过流程定义获取业务ids
    private List<String> getPassedList(String procDefId) {
        List<String> businessKeys = new ArrayList<>();
        try {
            // 获取本月已通过的申请记录
            String format = DateUtils.format(new Date(), "yyyy-MM");
            List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery()
                    .processDefinitionKey(procDefId)
                    .finished()
                    .notDeleted()
                    // 在某个时间之后结束
                    .finishedAfter(DateUtils.parseDate(format,"yyyy-MM"))
                    .orderByProcessInstanceStartTime().desc()
                    .list();
            businessKeys = list.stream().map(HistoricProcessInstance::getBusinessKey).collect(Collectors.toList());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return businessKeys;
    }

    @Override
    public ReturnDTO remindListPage() {
        List<EquipmentFixedAssets> list = equipmentWorkbenchMapper.remindListPage();
        return ReturnUtil.success(list);
    }

    @Override
    public ReturnDTO measureTrend() {
        String startTime = DateUtil.format(new Date(),"yyyy-MM");
        String endTime = getEndTime();
        List<EquipmentWorkbenchResponse> resList = equipmentWorkbenchMapper.measureTrend(startTime,endTime);
        return ReturnUtil.success(getResultList(resList));
    }

    @Override
    public ReturnDTO standardTrend() {
        String startTime = DateUtil.format(new Date(),"yyyy-MM");
        String endTime = getEndTime();
        List<EquipmentWorkbenchResponse> resList = equipmentWorkbenchMapper.standardTrend(startTime,endTime);
        return ReturnUtil.success(getResultList(resList));
    }

    @Override
    public ReturnDTO myselfEquipment() {
        EquipmentWorkbenchResponse response = new EquipmentWorkbenchResponse();
        AuthUser user = ShiroKit.getUser();
        Assert.isFalse(Objects.isNull(user), () -> {
            throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED);
        });
        // 待检定数量 通过提出设备检修申请获取本月申请通过的业务id
        List<String> businessKeys = getPassedList(getProcDefId(ApplyFromIdEnum.DEVICE_FIX_APPROVAL.getCode()));
        if(businessKeys.size()==0){
            response.setVerifiedNum(0);
            response.setOvertimeNum(0);
        }else {
            // 查询出设备负责人为当前登录用户数量
            response.setVerifiedNum(equipmentWorkbenchMapper.queryVerifiedNum(businessKeys, String.valueOf(user.getId())));
            // 通过判断检修申请中的检修时间是否超过设备检定周期判断是否超期
            response.setOvertimeNum(equipmentWorkbenchMapper.queryOvertimeNum(businessKeys, String.valueOf(user.getId())));
        }
        return  ReturnUtil.success(response);
    }

    public List<EquipmentWorkbenchResponse> getResultList(List<EquipmentWorkbenchResponse> resList) {
        if(resList.size()<12){
            List<String> monthList = getMonthList(12);
            resList.forEach(res->{
                monthList.remove(res.getDate());
            });
            for (String month : monthList) {
                EquipmentWorkbenchResponse result = new EquipmentWorkbenchResponse();
                result.setDate(month);
                result.setCount("0");
                resList.add(result);
            }
        }
        List<EquipmentWorkbenchResponse> newList = resList.stream().
                sorted(Comparator.comparing(EquipmentWorkbenchResponse::getDate)).
                collect(Collectors.toList());
        return newList;
    }

    public String getEndTime() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");
        Date date = new Date();
        Calendar calendar = Calendar.getInstance();
        // 设置为当前时间
        calendar.setTime(date);
        calendar.add(Calendar.MONTH,12);
        date = calendar.getTime();
        return format.format(date);
    }
    public List<String> getMonthList(Integer count) {
        List<String> resList = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");
            Date date = new Date();
            Calendar calendar = Calendar.getInstance();
            // 设置为当前时间
            calendar.setTime(date);
            calendar.add(Calendar.MONTH,i);
            // 设置为上一个月
            date = calendar.getTime();
            String dateStr = format.format(date);
            resList.add(dateStr);
        }
        return resList;
    }
}
