package com.yeejoin.amos.boot.module.tcm.biz.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.yeejoin.amos.boot.biz.common.utils.DateUtils;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.boot.module.tcm.api.common.BizCommonConstant;
import com.yeejoin.amos.boot.module.tcm.api.dto.TzsTwoStaffingCompanyCheckDto;
import com.yeejoin.amos.boot.module.tcm.api.dto.TzsTwoStaffingCompanyDto;
import com.yeejoin.amos.boot.module.tcm.api.dto.TzsTwoStaffingDto;
import com.yeejoin.amos.boot.module.tcm.api.entity.TzsTwoStaffing;
import com.yeejoin.amos.boot.module.tcm.api.enums.SupervisoryEnum;
import com.yeejoin.amos.boot.module.tcm.api.mapper.TzsTwoStaffingMapper;
import com.yeejoin.amos.boot.module.tcm.api.service.ITzsTwoStaffingService;
import lombok.extern.slf4j.Slf4j;
import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StopWatch;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.rdbms.service.BaseService;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 服务实现类
 *
 * @author system_generator
 * @date 2023-10-27
 */
@Service
@Slf4j
public class TzsTwoStaffingServiceImpl extends BaseService<TzsTwoStaffingDto, TzsTwoStaffing, TzsTwoStaffingMapper> implements ITzsTwoStaffingService {

    // 监管列表key
    private static final String REGULATOR_UNIT_LIST = "REGULATOR_UNIT_LIST";

	@Autowired
	RedisUtils redisUtils;

	@Autowired
	TzsTwoStaffingMapper tzsTwoStaffingMapper;

	@Override
	@Scheduled(cron = "0 0 2,13 * * ?")
	@SchedulerLock(name = "twoStaffingStatisticsTask", lockAtMostFor = "PT1H")
	public void generateTwoStaffingStatistics() {
		StopWatch timeWatch = new StopWatch();
		timeWatch.start();
	    // 所有监管单位列表
        List<LinkedHashMap<String, Object>> supervisionList = getSupervisionList();
        // 所有企业人员配备情况列表
        List<TzsTwoStaffingCompanyDto> staffingCompanyList = tzsTwoStaffingMapper.getListAll();
        // 两员配备统计列表
        List<TzsTwoStaffingDto> allStaffingDto = Lists.newArrayList();
        supervisionList.forEach(i -> {
            TzsTwoStaffingDto useUnitTwoStaffingDto = new TzsTwoStaffingDto();
            TzsTwoStaffingDto productUnitTwoStaffingDto = new TzsTwoStaffingDto();
            List<TzsTwoStaffingCompanyDto> useUnit =
                    staffingCompanyList.stream().filter(ii -> ii.getSuperviseOrgCode().startsWith(i.get("orgCode").toString()) && ii.getUnitType().contains("使用单位")).collect(Collectors.toList());
            // 使用单位总数
            int useUnitCount = useUnit.size();
            // 已完成单位数
            int useUnitFinished = useUnit.stream().mapToInt(s -> Integer.parseInt(s.getUseDone())).sum();
            // 已配备主要负责人单位数
            int useUnitMainChargerFinished = useUnit.stream().mapToInt(s -> Integer.parseInt(s.getMainCharger())).sum();

	        if (useUnitCount == 0) {
		        useUnitTwoStaffingDto.setCompletionRatio("0%");
		        useUnitTwoStaffingDto.setProportion("0%");
	        } else {
		        DecimalFormat decimalFormat = new DecimalFormat("0.##");
		        BigDecimal result = new BigDecimal(useUnitFinished).divide(new BigDecimal(useUnitCount), 4, RoundingMode.HALF_UP);
		        useUnitTwoStaffingDto.setCompletionRatio(decimalFormat.format(result.multiply(new BigDecimal(100))) + "%");
		        result = new BigDecimal(useUnitMainChargerFinished).divide(new BigDecimal(useUnitCount), 4, RoundingMode.HALF_UP);
		        useUnitTwoStaffingDto.setProportion(decimalFormat.format(result.multiply(new BigDecimal(100))) + "%");
	        }

	        useUnitTwoStaffingDto.setUnitType("使用单位");
	        useUnitTwoStaffingDto.setNumberOfUnits(useUnitCount);
	        useUnitTwoStaffingDto.setNumberOfCompletedUnits(useUnitFinished);
	        useUnitTwoStaffingDto.setResponsibleUnitsAllocateNumber(useUnitMainChargerFinished);
            useUnitTwoStaffingDto.setSupervisoryUnitId(i.get("sequenceNbr").toString());
            useUnitTwoStaffingDto.setSupervisoryUnitLevel(i.get("level").toString());
            useUnitTwoStaffingDto.setSupervisoryUnitName(i.get("companyName").toString());
            useUnitTwoStaffingDto.setSupervisoryUnitOrgcode(i.get("orgCode").toString());

	        allStaffingDto.add(useUnitTwoStaffingDto);

            List<TzsTwoStaffingCompanyDto> productUnit =
                    staffingCompanyList.stream().filter(ii -> ii.getSuperviseOrgCode().startsWith(i.get("orgCode").toString()) && (ii.getUnitType().contains("充装单位") || ii.getUnitType().contains("安装改造维修单位") || ii.getUnitType().contains("制造单位") || ii.getUnitType().contains("设计单位"))).collect(Collectors.toList());
            // 生产单位总数
            int productUnitCount = productUnit.size();
            // 已完成单位数
            int productUnitFinished = productUnit.stream().mapToInt(s -> Integer.parseInt(s.getProductDone())).sum();
            // 已配备主要负责人单位数
            int productUnitMainChargerFinished =
                    productUnit.stream().mapToInt(s -> Integer.parseInt(s.getMainCharger())).sum();

	        if (productUnitCount == 0) {
		        productUnitTwoStaffingDto.setCompletionRatio("0%");
		        productUnitTwoStaffingDto.setProportion("0%");
	        } else {
		        DecimalFormat decimalFormat = new DecimalFormat("0.##");
		        BigDecimal result = new BigDecimal(productUnitFinished).divide(new BigDecimal(productUnitCount), 4, RoundingMode.HALF_UP);
		        productUnitTwoStaffingDto.setCompletionRatio(decimalFormat.format(result.multiply(new BigDecimal(100))) + "%");
		        result = new BigDecimal(productUnitMainChargerFinished).divide(new BigDecimal(productUnitCount), 4, RoundingMode.HALF_UP);
		        productUnitTwoStaffingDto.setProportion(decimalFormat.format(result.multiply(new BigDecimal(100))) + "%");
	        }

            productUnitTwoStaffingDto.setUnitType("生产单位");
            productUnitTwoStaffingDto.setNumberOfUnits(productUnitCount);
            productUnitTwoStaffingDto.setNumberOfCompletedUnits(productUnitFinished);
            productUnitTwoStaffingDto.setResponsibleUnitsAllocateNumber(productUnitMainChargerFinished);
            productUnitTwoStaffingDto.setSupervisoryUnitId(i.get("sequenceNbr").toString());
            productUnitTwoStaffingDto.setSupervisoryUnitLevel(i.get("level").toString());
            productUnitTwoStaffingDto.setSupervisoryUnitName(i.get("companyName").toString());
            productUnitTwoStaffingDto.setSupervisoryUnitOrgcode(i.get("orgCode").toString());

	        allStaffingDto.add(productUnitTwoStaffingDto);
        });
        // 先清两员配备统计空表
        tzsTwoStaffingMapper.truncateTwoStaffingStatistics();
        // 再重新生成统计信息
		List<TzsTwoStaffing> allStaffing = Lists.newArrayList();
		if (!ValidationUtil.isEmpty(allStaffingDto)) {
			allStaffingDto.forEach(e -> {
				TzsTwoStaffing tzsTwoStaffing = new TzsTwoStaffing();
				BeanUtils.copyProperties(e, tzsTwoStaffing);
				allStaffing.add(tzsTwoStaffing);
			});
		}
        this.saveBatch(allStaffing);
		timeWatch.stop();
		log.info("两员配备统计耗时{}秒/n", timeWatch.getTotalTimeSeconds());
	}

    @Override
    public Page<TzsTwoStaffingCompanyCheckDto> getCompanyCheckList(String orgCode,
                                                                   TzsTwoStaffingCompanyCheckDto companyDto,
                                                                   Page<TzsTwoStaffingCompanyCheckDto> page) {
        Date nowDay = new Date();
        String day = DateUtils.convertDateToString(nowDay, DateUtils.DATE_PATTERN);
        String startDay = day + " 00:00:00";
        String endDay = day + " 23:59:59";
        companyDto.setPlanType(ObjectUtils.isEmpty(companyDto.getPlanType()) ? "1" : companyDto.getPlanType());
        companyDto.setCheckStartTime(ObjectUtils.isEmpty(companyDto.getCheckStartTime()) ? startDay : companyDto.getCheckStartTime());
        companyDto.setCheckEndTime(ObjectUtils.isEmpty(companyDto.getCheckEndTime()) ? endDay : companyDto.getCheckEndTime());
        // todo 此处统计表名通过接口查询得到 接口暂未实现
        String planType = companyDto.getPlanType();
        String staticTableName = "p_static_day";
        return tzsTwoStaffingMapper.getCompanyCheckList(page, orgCode, staticTableName, companyDto);
    }


    public List<LinkedHashMap<String, Object>> getSupervisionList() {
		List<LinkedHashMap<String, Object>> supervisionList =
				(List<LinkedHashMap<String, Object>>) redisUtils.get(BizCommonConstant.REGULATOR_UNIT_LIST);
		if (ValidationUtil.isEmpty(supervisionList)) {
			// 监管单位树
			List<LinkedHashMap<String, Object>> supervisionTree =
					(List<LinkedHashMap<String, Object>>) redisUtils.get(BizCommonConstant.COMPANY_TREE_REDIS_KEY);

			if (!ValidationUtil.isEmpty(supervisionTree)) {
				List<LinkedHashMap<String, Object>> supervisionTree2List = tree2List(supervisionTree);
				redisUtils.set(REGULATOR_UNIT_LIST, supervisionTree2List);
				return supervisionTree2List;
			}
		}
		return supervisionList;
	}

    @Override
    public List<TzsTwoStaffing> getStatisticsMessage(List<LinkedHashMap> list, String type) {
        String orgCode = null;
        String nextLevel = null;
        SupervisoryEnum enumByLevel = null;
        if (!ObjectUtils.isEmpty(list) && !ObjectUtils.isEmpty(list.get(0))) {
            orgCode = String.valueOf(list.get(0).get("orgCode"));
            enumByLevel = SupervisoryEnum.getEnumByLevel(String.valueOf(list.get(0).get("level")));
            nextLevel = !ObjectUtils.isEmpty(enumByLevel) ? enumByLevel.getNextLevel() : null;
        }
        DecimalFormat decimalFormat = new DecimalFormat("0.00");
        if (!ObjectUtils.isEmpty(orgCode)) {
            if ("50*56".equals(orgCode)){
                nextLevel = "organization";
            }
            List<TzsTwoStaffing> listByOrgCode = this.getBaseMapper().getListByOrgCode(orgCode, type, nextLevel);
            if (ObjectUtils.isEmpty(listByOrgCode)){
                listByOrgCode = this.getBaseMapper().getListByOrgCode(orgCode, type, enumByLevel.getLevel());
            }
            TzsTwoStaffing tzsTwoStaffing = new TzsTwoStaffing();
            tzsTwoStaffing.setSupervisoryUnitName("汇总");
            listByOrgCode.forEach(item -> {
                tzsTwoStaffing.setNumberOfUnits(!ObjectUtils.isEmpty(tzsTwoStaffing.getNumberOfUnits()) ? +tzsTwoStaffing.getNumberOfUnits() + item.getNumberOfUnits() : item.getNumberOfUnits());
                tzsTwoStaffing.setNumberOfCompletedUnits(!ObjectUtils.isEmpty(tzsTwoStaffing.getNumberOfCompletedUnits()) ? tzsTwoStaffing.getNumberOfCompletedUnits() + item.getNumberOfCompletedUnits() : item.getNumberOfCompletedUnits());
                tzsTwoStaffing.setResponsibleUnitsAllocateNumber(!ObjectUtils.isEmpty(tzsTwoStaffing.getResponsibleUnitsAllocateNumber()) ? tzsTwoStaffing.getResponsibleUnitsAllocateNumber() + item.getResponsibleUnitsAllocateNumber() : item.getResponsibleUnitsAllocateNumber());

            });
            if (ObjectUtils.isEmpty(tzsTwoStaffing.getNumberOfCompletedUnits()) || ObjectUtils.isEmpty(tzsTwoStaffing.getNumberOfUnits()) || tzsTwoStaffing.getNumberOfUnits() == 0 || tzsTwoStaffing.getNumberOfCompletedUnits() == 0) {
                tzsTwoStaffing.setCompletionRatio("0%");

            } else {
                BigDecimal bigDecimal = new BigDecimal(tzsTwoStaffing.getNumberOfCompletedUnits().toString());
                BigDecimal bigDecimal1 = new BigDecimal(tzsTwoStaffing.getNumberOfUnits().toString());
                BigDecimal divide = bigDecimal.divide(bigDecimal1, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("100"));
                tzsTwoStaffing.setCompletionRatio(decimalFormat.format(divide) + "%");

            }
            if (ObjectUtils.isEmpty(tzsTwoStaffing.getResponsibleUnitsAllocateNumber()) || tzsTwoStaffing.getResponsibleUnitsAllocateNumber() == 0
                    || ObjectUtils.isEmpty(tzsTwoStaffing.getNumberOfUnits()) || tzsTwoStaffing.getNumberOfUnits() == 0) {
                tzsTwoStaffing.setProportion("0%");
            } else {
                BigDecimal bigDecimal = new BigDecimal(tzsTwoStaffing.getResponsibleUnitsAllocateNumber().toString());
                BigDecimal bigDecimal1 = new BigDecimal(tzsTwoStaffing.getNumberOfUnits().toString());
                BigDecimal divide = bigDecimal.divide(bigDecimal1, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("100"));
                tzsTwoStaffing.setProportion(decimalFormat.format(divide) + "%");

            }
            listByOrgCode.add(tzsTwoStaffing);
            return listByOrgCode;
        }
        return null;
    }

    private List<LinkedHashMap<String, Object>> tree2List(List<LinkedHashMap<String, Object>> supervisionList) {
		List<LinkedHashMap<String, Object>> result = Lists.newArrayList();
		for (LinkedHashMap<String, Object> map : supervisionList) {
			result.add(map);
			if (!ValidationUtil.isEmpty(map.get("children"))) {
				List<LinkedHashMap<String, Object>> childrenList = tree2List((List<LinkedHashMap<String, Object>>) map.get("children"));
				result.addAll(childrenList);
			}
		}
		if (result.size() > 0) {
			for (LinkedHashMap<String, Object> map : result) {
				map.put("children", null);
			}
		}
		return result;
	}

    @Override
    public Page<TzsTwoStaffingCompanyDto> getCompanyList(String orgCode, TzsTwoStaffingCompanyDto companyDto, Page<TzsTwoStaffingCompanyDto> page) {

        Page<TzsTwoStaffingCompanyDto> companyList = tzsTwoStaffingMapper.getCompanyList(page, companyDto, orgCode);

        if(!ObjectUtils.isEmpty(companyList.getRecords())){
            for (TzsTwoStaffingCompanyDto item : companyList.getRecords()) {
                item.setCompleteNormal(Integer.valueOf(item.getCompleteNormal()) == 1 ? "是" : "否");
            }
        }
        return companyList;
    }
}