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

import cn.hutool.core.date.DateUtil;
import com.alibaba.excel.util.DateUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.casic.missiles.core.page.PageFactory;
import com.casic.missiles.dto.business.board.BoardDeptComprehensiveRequest;
import com.casic.missiles.dto.business.board.BoardDeptComprehensiveResponse;
import com.casic.missiles.dto.cockpit.*;
import com.casic.missiles.dto.equipment.FixedAssetRequest;
import com.casic.missiles.dto.equipment.StandardEquipmentRequest;
import com.casic.missiles.enums.system.ApplyFromIdEnum;
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.meter.MeterPriceMapper;
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.page.PageQuery;
import com.casic.missiles.model.system.SystemFlowForm;
import com.casic.missiles.service.business.IBusinessBoardService;
import com.casic.missiles.service.cockpit.IAssetMonitorService;
import com.casic.missiles.service.system.ISystemFlowFormService;
import org.flowable.engine.HistoryService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description:
 * @Author: wangpeng
 * @Date: 2023/6/13 15:18
 */
@Service
public class AssetMonitorServiceImpl implements IAssetMonitorService {
    @Resource
    private MeterFixedAssetsMapper meterFixedAssetsMapper;
    @Resource
    private EquipmentStandardEquipmentMapper meterStandardEquipmentMapper;
    @Resource
    private MeterPriceMapper meterPriceMapper;
    @Resource
    private ISystemFlowFormService flowFormService;
    @Resource
    private HistoryService historyService;
    @Resource
    private EquipmentApplyEquipmentMapper equipmentMapper;
    @Autowired
    private IBusinessBoardService boardService;

    @Override
    public AssetManagementResponse assetManagement() {
        AssetManagementResponse response = new AssetManagementResponse();
        //测量设备总数
        QueryWrapper<EquipmentFixedAssets> wrapper = new QueryWrapper<>();
        wrapper.eq("asset_type", "1");
        wrapper.eq("is_del", 0);
        response.setDeviceCount(meterFixedAssetsMapper.selectCount(wrapper));
        //标准装置总数
        QueryWrapper<EquipmentStandardEquipment> standardEquipmentQueryWrapper = new QueryWrapper<>();
        response.setEquipmentCount(meterStandardEquipmentMapper.selectCount(standardEquipmentQueryWrapper));
        //能力总数
        Integer i = meterPriceMapper.selectCountByItem();
        response.setAbilityCount(i);
        return response;
    }

    @Override
    public EquipmentResponse equipment() {
        EquipmentResponse response = new EquipmentResponse();
        // 测量设备在用
        QueryWrapper<EquipmentFixedAssets> wrapper = new QueryWrapper<>();
        wrapper.eq("asset_type", "1");
        wrapper.eq("manager_state", "1");
        response.setInUseEquipment(meterFixedAssetsMapper.selectCount(wrapper));
        // 测量设备闲置
        response.setIdleEquipment(getApplyCount(ApplyFromIdEnum.DEVICE_UNUSED_APPROVAL.getCode()));
        // 测量设备封存
        response.setSealingEquipment(getApplyCount(ApplyFromIdEnum.DEVICE_SEALED_APPROVAL.getCode()));
        return response;
    }

    @Override
    public List<ExpireDeviceStatisticsResponse> expireDeviceStatistics() {
        List<ExpireDeviceStatisticsResponse> list = meterFixedAssetsMapper.selectExpireDeviceStatistics();
        List<String> dateList = com.casic.missiles.utils.DateUtils.getCurrentDateMonthList();
        List<ExpireDeviceStatisticsResponse> finalList = new ArrayList<>();
        if(CollectionUtils.isEmpty(list)){
            for (String date : dateList) {
                ExpireDeviceStatisticsResponse statisticsResponse = new ExpireDeviceStatisticsResponse();
                statisticsResponse.setMonth(date);
                statisticsResponse.setExpiredQuantity(0);
                finalList.add(statisticsResponse);
            }
        }else{
            for (String date : dateList) {
                Integer flag = 0;
                for (ExpireDeviceStatisticsResponse dto : list) {
                    if (dto.getMonth().equals(date)) {
                        finalList.add(dto);
                        flag = 1;
                    }
                }
                if (flag == 0) {
                    ExpireDeviceStatisticsResponse statisticsResponse = new ExpireDeviceStatisticsResponse();
                    statisticsResponse.setMonth(date);
                    statisticsResponse.setExpiredQuantity(0);
                    finalList.add(statisticsResponse);
                }
            }
        }
        return finalList;
    }

    @Override
    public List<EquipmentFixedAssets> expireDeviceList() {
        FixedAssetRequest request = new FixedAssetRequest();
        request.setAssetType(1);
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, 0);
        c.set(Calendar.DAY_OF_MONTH, 1);
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        Date m = c.getTime();
        String format = DateUtil.format(m, "yyyy-MM-dd HH:mm:ss");
        request.setValidDateStart(format);
        request.setValidDateEnd(DateUtil.now());
        PageQuery pageQuery = new PageQuery();
        pageQuery.setPageNo(0);
        pageQuery.setPageSize(10000);
        Page<EquipmentFixedAssets> page = PageFactory.createPage(pageQuery);
        Page<EquipmentFixedAssets> meterFixedAssetsPage = meterFixedAssetsMapper.listPage(page, request);
        return meterFixedAssetsPage.getRecords();
    }

    @Override
    public DeviceMeasureResponse deviceMeasure() {
        BoardDeptComprehensiveRequest request = new BoardDeptComprehensiveRequest();
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, -1);
        Date m = c.getTime();
        String format = DateUtil.format(m, "yyyy-MM-dd HH:mm:ss");
        request.setStartTime(format);
        request.setEndTime(DateUtil.now());
        List<BoardDeptComprehensiveResponse> list = boardService.deptComprehensive(request);
        if(CollectionUtils.isEmpty(list)){
            return new DeviceMeasureResponse();
        }
        BigDecimal deviceTimelyTotal = new BigDecimal(0);
        BigDecimal deviceQualifyTotal = new BigDecimal(0);
        BigDecimal deviceRepairTotal = new BigDecimal(0);
        list.forEach(response -> {
            NumberFormat nf = NumberFormat.getPercentInstance();
            try {
                Number number = nf.parse(response.getDeviceTimelyRate());
                deviceTimelyTotal.add(BigDecimal.valueOf(number.doubleValue()));
                Number number1 = nf.parse(response.getDeviceQualifyRate());
                deviceQualifyTotal.add(BigDecimal.valueOf(number1.doubleValue()));
                Number number2 = nf.parse(response.getDeviceRepairRate());
                deviceRepairTotal.add(BigDecimal.valueOf(number2.doubleValue()));
            } catch (ParseException e) {
                return;
            }
        });
        DeviceMeasureResponse deviceMeasureResponse = new DeviceMeasureResponse();
        deviceMeasureResponse.setDeviceTimelyRate(deviceTimelyTotal.divide(BigDecimal.valueOf(list.size()),2, BigDecimal.ROUND_HALF_UP).toPlainString() + "%");
        deviceMeasureResponse.setDeviceQualifyRate(deviceQualifyTotal.divide(BigDecimal.valueOf(list.size()),2, BigDecimal.ROUND_HALF_UP).toPlainString() + "%");
        deviceMeasureResponse.setDeviceRepairRate(deviceRepairTotal.divide(BigDecimal.valueOf(list.size()),2, BigDecimal.ROUND_HALF_UP).toPlainString() + "%");
        return deviceMeasureResponse;
    }

    @Override
    public StandardEquipmentResponse standardEquipment() {
        StandardEquipmentResponse response = new StandardEquipmentResponse();
        // 测量设备在用
        QueryWrapper<EquipmentStandardEquipment> standardEquipmentQueryWrapper = new QueryWrapper<>();
        standardEquipmentQueryWrapper.eq("manager_state", "1");
        response.setInUseEquipment(meterStandardEquipmentMapper.selectCount(standardEquipmentQueryWrapper));
        // 标准装置暂停
        response.setPauseEquipment(getApplyCount(ApplyFromIdEnum.STANDARD_PAUSE_APPROVAL.getCode()));
        // 标准装置撤销
        response.setRevokeEquipment(getApplyCount(ApplyFromIdEnum.STANDARD_REVERT_APPROVAL.getCode()));
        return response;
    }

    @Override
    public List<EquipmentStandardEquipment> expireEquipmentList() {
        StandardEquipmentRequest request = new StandardEquipmentRequest();
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, 0);
        c.set(Calendar.DAY_OF_MONTH, 1);
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        Date m = c.getTime();
        String format = DateUtil.format(m, "yyyy-MM-dd HH:mm:ss");
        request.setValidStartTime(format);
        request.setValidEndTime(DateUtil.now());
        PageQuery pageQuery = new PageQuery();
        pageQuery.setPageNo(0);
        pageQuery.setPageSize(10000);
        Page<EquipmentStandardEquipment> page = PageFactory.createPage(pageQuery);
        Page<EquipmentStandardEquipment> resultPage = meterStandardEquipmentMapper.remindListPage(page, request);
        return resultPage.getRecords();
    }

    @Override
    public List<ExpireEquipmentStatisticsResponse> expireEquipmentStatistics() {
        List<ExpireEquipmentStatisticsResponse> list = meterStandardEquipmentMapper.selectExpireEquipmentStatistics();
        List<String> dateList = com.casic.missiles.utils.DateUtils.getCurrentDateMonthList();
        List<ExpireEquipmentStatisticsResponse> finalList = new ArrayList<>();
        if(CollectionUtils.isEmpty(list)){
            for (String date : dateList) {
                ExpireEquipmentStatisticsResponse statisticsResponse = new ExpireEquipmentStatisticsResponse();
                statisticsResponse.setMonth(date);
                statisticsResponse.setExpiredQuantity(0);
                finalList.add(statisticsResponse);
            }
        }else{
            for (String date : dateList) {
                Integer flag = 0;
                for (ExpireEquipmentStatisticsResponse dto : list) {
                    if (dto.getMonth().equals(date)) {
                        finalList.add(dto);
                        flag = 1;
                    }
                }
                if (flag == 0) {
                    ExpireEquipmentStatisticsResponse statisticsResponse = new ExpireEquipmentStatisticsResponse();
                    statisticsResponse.setMonth(date);
                    statisticsResponse.setExpiredQuantity(0);
                    finalList.add(statisticsResponse);
                }
            }
        }
        return finalList;
    }

    private Long getApplyCount(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);
        }
        return count;
    }

    // 通过流程定义获取业务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;
    }

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