package com.ningdatech.carapi.report.manage;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ningdatech.basic.function.VUtils;
import com.ningdatech.basic.model.PageVo;
import com.ningdatech.basic.util.NdDateUtils;
import com.ningdatech.basic.util.StrPool;
import com.ningdatech.carapi.car.vehicle.contants.VehicleContant;
import com.ningdatech.carapi.common.constant.UserRoleTypeEnum;
import com.ningdatech.carapi.common.contants.DefValConstants;
import com.ningdatech.carapi.report.constant.DataUploadAuditStatusEnum;
import com.ningdatech.carapi.report.constant.DataUploadAuditTypeEnum;
import com.ningdatech.carapi.report.constant.UploadDataTypeEnum;
import com.ningdatech.carapi.report.model.entity.*;
import com.ningdatech.carapi.report.model.po.ReqBulkCementThreeCityUsageDataUploadPO;
import com.ningdatech.carapi.report.model.po.ReqDataUploadListPO;
import com.ningdatech.carapi.report.model.vo.ResBulkCementThreeCityUsageDataUploadDetailVO;
import com.ningdatech.carapi.report.model.vo.ResDataUploadListVO;
import com.ningdatech.carapi.report.service.*;
import com.ningdatech.carapi.sys.entity.dto.CompanyDTO;
import com.ningdatech.carapi.sys.entity.dto.RegionDTO;
import com.ningdatech.carapi.sys.helper.CompaniesCacheHelper;
import com.ningdatech.carapi.sys.helper.RegionsCacheHelper;
import com.ningdatech.carapi.user.security.auth.model.UserInfoDetails;
import com.ningdatech.carapi.user.util.LoginUserUtil;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author CMM
 * @since 2023/09/28 11:15
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class BulkCementThreeCityUsageBulletinManage {

    private final IBulkCementDirectReportSystemAuditRecordService auditRecordService;
    private final IBulkCementDirectReportSystemAuditInfoService auditInfoService;
    private final RegionsCacheHelper regionsCacheHelper;
    private final IBulkCementThreeCityUsageBulletinService bulkCementThreeCityUsageBulletinService;
    private final IBulkCementDirectReportSystemUniversalIndexService universalIndexService;
    private final IBulkCementDirectReportSystemDataRelevanceService dataRelevanceService;
    private final CompaniesCacheHelper companiesCacheHelper;
    public PageVo<ResDataUploadListVO> dataUploadList(ReqDataUploadListPO req) {

        UserInfoDetails userDetail = LoginUserUtil.loginUserDetail();
        Long regionId = userDetail.getRegionId();

        Page<BulkCementThreeCityUsageBulletin> page = req.page();
        // 根据所属区域查出对应的散装水泥供应量数据上报记录
        LambdaQueryWrapper<BulkCementThreeCityUsageBulletin> wrapper = Wrappers.lambdaQuery(BulkCementThreeCityUsageBulletin.class);
        // 获取入参
        LocalDateTime reportStartMonth = req.getReportStartMonth();
        LocalDateTime reportEndMonth = req.getReportEndMonth();
        Integer auditStatus = req.getAuditStatus();
        wrapper.ge(Objects.nonNull(reportStartMonth), BulkCementThreeCityUsageBulletin::getReportMonth, reportStartMonth)
                .le(Objects.nonNull(reportEndMonth), BulkCementThreeCityUsageBulletin::getReportMonth, reportEndMonth)
                .eq(Objects.nonNull(auditStatus),BulkCementThreeCityUsageBulletin::getAuditStatus,auditStatus)
                .eq(BulkCementThreeCityUsageBulletin::getRegionId,regionId)
                .orderByDesc(BulkCementThreeCityUsageBulletin::getReportMonth);
                //.isNotNull(BulkCementThreeCityUsageBulletin::getAuditInfoId);
        bulkCementThreeCityUsageBulletinService.page(page,wrapper);
        List<BulkCementThreeCityUsageBulletin> records = page.getRecords();
        if (CollUtil.isEmpty(records)){
            return PageVo.empty();
        }
        // 获取审核信息
        List<Long> auditInfoIdList = records.stream().map(BulkCementThreeCityUsageBulletin::getAuditInfoId).collect(Collectors.toList());
        Map<Long, BulkCementDirectReportSystemAuditInfo> auditInfoMap = auditInfoService.list(Wrappers.lambdaQuery(BulkCementDirectReportSystemAuditInfo.class).in(BulkCementDirectReportSystemAuditInfo::getId, auditInfoIdList))
                .stream().collect(Collectors.toMap(BulkCementDirectReportSystemAuditInfo::getId, v -> v));
        List<ResDataUploadListVO> resVos = records.stream().map(r -> {
            ResDataUploadListVO vo = new ResDataUploadListVO();
            LocalDateTime month = r.getReportMonth();
            String reportMonthStr = NdDateUtils.format(month, NdDateUtils.DEFAULT_MONTH_FORMAT);
            LocalDateTime reportMonth = LocalDateTimeUtil.parse(reportMonthStr, DateTimeFormatter.ofPattern(DatePattern.NORM_MONTH_PATTERN));
            vo.setRegionId(r.getRegionId());
            vo.setReportMonth(reportMonth);
            vo.setAuditDataId(r.getId());
            BulkCementDirectReportSystemAuditInfo auditInfo = auditInfoMap.get(r.getAuditInfoId());
            if (Objects.nonNull(auditInfo)) {
                vo.setAuditOpinion(auditInfo.getAuditOpinion());
            }
            vo.setAuditStatus(r.getAuditStatus());
            String desc = DataUploadAuditStatusEnum.getDescByCode(r.getAuditStatus());
            vo.setAuditStatusName(desc);
            vo.setCreateOn(r.getCreateOn());
            return vo;
        }).collect(Collectors.toList());
        return PageVo.of(resVos, page.getTotal());
    }

    @Transactional(rollbackFor = Exception.class)
    public String bulkCementThreeCityUsageDataUpload(ReqBulkCementThreeCityUsageDataUploadPO req) {
        // 获取登录用户信息
        UserInfoDetails userDetail = LoginUserUtil.loginUserDetail();
        LocalDateTime reportMonth = req.getReportMonth();
        Long regionId = userDetail.getRegionId();

        // 如果登录用户为区县散办
        if (UserRoleTypeEnum.REGION_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId())) {

            VUtils.isTrue(Objects.isNull(reportMonth)).throwMessage("请选择上报月份!");

            // 提交市级审核申请
            BulkCementDirectReportSystemAuditInfo cityAuditInfo = new BulkCementDirectReportSystemAuditInfo();
            assemblyAuditInfo(cityAuditInfo, DataUploadAuditStatusEnum.UNDER_AUDIT, userDetail);
            cityAuditInfo.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode());
            auditInfoService.save(cityAuditInfo);

            // 保存上报数据信息
            BulkCementThreeCityUsageBulletin bulkCementThreeCityUsageBulletin = new BulkCementThreeCityUsageBulletin();
            // 区县的区域ID
            Long countryRegionId = userDetail.getRegionId();
            // 获取所在市的区域ID
            RegionDTO regionDto = regionsCacheHelper.getByRegionId(countryRegionId);
            Long parentId = regionDto.getParentId();
            // 判断上报月份所在市的关联数据不存在
            RegionDTO cityRegionDto = regionsCacheHelper.getByRegionId(parentId);
            BulkCementDirectReportSystemDataRelevance cityData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class)
                    .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, parentId)
                    .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.CITY_AUDIT.getCode())
                    .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, reportMonth)
                    .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.BULK_CEMENT_THREE_CITY_USAGE_BULLETIN.getCode()));

            // 判断当前地区当前上报月份数据是否已经存在,如果已经存在，删除原数据并更新市、省关联数据列表
            checkUploadData(reportMonth, regionId, cityData);
            Long dataId = req.getId();
            // 上报数据不为空，说明为重新提交
            if (Objects.nonNull(dataId)) {
                BulkCementThreeCityUsageBulletin oldData = bulkCementThreeCityUsageBulletinService.getById(dataId);
                VUtils.isTrue(Objects.isNull(oldData)).throwMessage("重新提交数据不存在!");
                // 更新市级关联数据
                updateCityData(cityData,oldData);
                // 删除被退回的数据
                bulkCementThreeCityUsageBulletinService.removeById(oldData);

            }

            assemblyData(req, userDetail, bulkCementThreeCityUsageBulletin);
            bulkCementThreeCityUsageBulletin.setAuditInfoId(cityAuditInfo.getId());
            bulkCementThreeCityUsageBulletin.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode());
            bulkCementThreeCityUsageBulletinService.saveOrUpdate(bulkCementThreeCityUsageBulletin);

            // 补充数据审核表信息
            BulkCementDirectReportSystemAuditRecord auditRecord = new BulkCementDirectReportSystemAuditRecord();
            assemblyAuditRecord(userDetail, bulkCementThreeCityUsageBulletin.getId(), cityAuditInfo.getId(), auditRecord);
            auditRecord.setReportMonth(reportMonth);
            auditRecord.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode());
            auditRecordService.save(auditRecord);

            // 补充所在市的关联数据信息
            if (Objects.isNull(cityData)) {
                BulkCementDirectReportSystemDataRelevance cityRelevanceData = new BulkCementDirectReportSystemDataRelevance();
                assemblyRelevanceData(userDetail, reportMonth, cityRelevanceData);
                cityRelevanceData.setRegionId(parentId);
                // 获取所在市散装中心所属的管理企业ID
                CompanyDTO companyDto = companiesCacheHelper.getByName(cityRegionDto.getRegionName() + VehicleContant.ADMIN_COMPANY_NAME);
                if (Objects.nonNull(companyDto)) {
                    cityRelevanceData.setCompanyId(companyDto.getId());
                }
                cityRelevanceData.setAuditType(DataUploadAuditTypeEnum.CITY_AUDIT.getCode());
                cityRelevanceData.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_THREE_CITY_USAGE_BULLETIN.getCode());
                // 有新上报的数据，就更新关联数据状态为未上报
                cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.NOT_REPORT.getCode());
                dataRelevanceService.saveOrUpdate(cityRelevanceData);
            }

        }
        // 如果登录用户是市级散办,更新审核状态(未上报、被退回)为审核中，并提交省级审核信息和审核记录
        else if (UserRoleTypeEnum.BULK_CEMENT_ADMIN_ROLE_ID.getId().equals(userDetail.getRoleId())) {

            Long relevanceDataId = req.getId();
            VUtils.isTrue(Objects.isNull(relevanceDataId)).throwMessage("请传入关联数据ID!");

            // 提交省级审核申请
            BulkCementDirectReportSystemAuditInfo provinceAuditInfo = new BulkCementDirectReportSystemAuditInfo();
            assemblyAuditInfo(provinceAuditInfo, DataUploadAuditStatusEnum.UNDER_AUDIT, userDetail);
            provinceAuditInfo.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode());
            auditInfoService.save(provinceAuditInfo);
            // 更新市级关联数据审核状态为审核中
            BulkCementDirectReportSystemDataRelevance cityRelevanceData = dataRelevanceService.getById(relevanceDataId);
            VUtils.isTrue(Objects.isNull(cityRelevanceData)).throwMessage("数据不存在!");
            // 关联审核信息ID
            cityRelevanceData.setUnitResponsiblePerson(req.getUnitResponsiblePerson());
            cityRelevanceData.setPreparer(req.getPreparer());
            cityRelevanceData.setReviewer(req.getReviewer());
            cityRelevanceData.setSubmissionDate(req.getSubmissionDate());
            cityRelevanceData.setAuditInfoId(provinceAuditInfo.getId());
            cityRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode());
            cityRelevanceData.setUpdateOn(LocalDateTime.now());
            cityRelevanceData.setUpdateBy(userDetail.getUserId());
            cityRelevanceData.setUnitResponsiblePerson(req.getUnitResponsiblePerson());
            cityRelevanceData.setPreparer(req.getPreparer());
            cityRelevanceData.setReviewer(req.getReviewer());
            cityRelevanceData.setSubmissionDate(req.getSubmissionDate());
            dataRelevanceService.updateById(cityRelevanceData);

            // 判断上报月份省关联数据是否存在
            BulkCementDirectReportSystemDataRelevance provinceData = dataRelevanceService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemDataRelevance.class)
                    .eq(BulkCementDirectReportSystemDataRelevance::getRegionId, DefValConstants.ZJREGION_ID)
                    .eq(BulkCementDirectReportSystemDataRelevance::getAuditType,DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode())
                    .eq(BulkCementDirectReportSystemDataRelevance::getReportMonth, reportMonth)
                    .eq(BulkCementDirectReportSystemDataRelevance::getAuditDataType, UploadDataTypeEnum.BULK_CEMENT_THREE_CITY_USAGE_BULLETIN.getCode()));

            // 如果上报月份省级关联数据不存在
            // 补充省散办关联数据信息
            if (Objects.isNull(provinceData)) {
                BulkCementDirectReportSystemDataRelevance provinceRelevanceData = new BulkCementDirectReportSystemDataRelevance();
                assemblyRelevanceData(userDetail, reportMonth, provinceRelevanceData);
                provinceRelevanceData.setAuditInfoId(provinceAuditInfo.getId());
                provinceRelevanceData.setRegionId(DefValConstants.ZJREGION_ID);
                provinceRelevanceData.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode());
                // 获取省散装中心所属的管理企业ID
                CompanyDTO companyDto = companiesCacheHelper.getByName(DefValConstants.PROVINCE + VehicleContant.ADMIN_COMPANY_NAME);
                if (Objects.nonNull(companyDto)) {
                    provinceRelevanceData.setCompanyId(companyDto.getId());
                }
                provinceRelevanceData.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_THREE_CITY_USAGE_BULLETIN.getCode());
                provinceRelevanceData.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode());
                dataRelevanceService.save(provinceRelevanceData);
            }
            // 创建省级审核记录
            BulkCementDirectReportSystemAuditRecord provinceAuditRecord = new BulkCementDirectReportSystemAuditRecord();
            assemblyAuditRecord(userDetail, cityRelevanceData.getId(), provinceAuditInfo.getId(), provinceAuditRecord);
            provinceAuditRecord.setReportMonth(cityRelevanceData.getReportMonth());
            provinceAuditRecord.setAuditType(DataUploadAuditTypeEnum.PROVINCE_AUDIT.getCode());
            auditRecordService.save(provinceAuditRecord);
        }
        return "上报成功!";
    }
    private void assemblyRelevanceData(UserInfoDetails userDetail, LocalDateTime reportMonth, BulkCementDirectReportSystemDataRelevance relevanceData) {
        relevanceData.setReportMonth(reportMonth);
        relevanceData.setCreateOn(LocalDateTime.now());
        relevanceData.setCreateBy(userDetail.getUserId());
        relevanceData.setUpdateOn(LocalDateTime.now());
        relevanceData.setUpdateBy(userDetail.getUserId());
        relevanceData.setLastUpdateTime(LocalDateTime.now());
    }

    private void assemblyAuditRecord(UserInfoDetails userDetail, Long auditDataId, Long auditInfoId, BulkCementDirectReportSystemAuditRecord auditRecord) {
        auditRecord.setAuditDataId(auditDataId);
        auditRecord.setAuditInfoId(auditInfoId);
        auditRecord.setAuditStatus(DataUploadAuditStatusEnum.UNDER_AUDIT.getCode());
        auditRecord.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_THREE_CITY_USAGE_BULLETIN.getCode());
        auditRecord.setCompanyId(userDetail.getCompanyId());
        auditRecord.setRegionId(userDetail.getRegionId());
        auditRecord.setCreateOn(LocalDateTime.now());
        auditRecord.setCreateBy(userDetail.getUserId());
        auditRecord.setUpdateOn(LocalDateTime.now());
        auditRecord.setUpdateBy(userDetail.getUserId());
    }

    private void assemblyAuditInfo(BulkCementDirectReportSystemAuditInfo auditInfo, DataUploadAuditStatusEnum underAudit, UserInfoDetails userDetail) {
        auditInfo.setAuditStatus(underAudit.getCode());
        auditInfo.setAuditDataType(UploadDataTypeEnum.BULK_CEMENT_THREE_CITY_USAGE_BULLETIN.getCode());
        auditInfo.setCreateOn(LocalDateTime.now());
        auditInfo.setCreateBy(userDetail.getUserId());
        auditInfo.setUpdateOn(LocalDateTime.now());
        auditInfo.setUpdateBy(userDetail.getUserId());
    }

    private void assemblyData(ReqBulkCementThreeCityUsageDataUploadPO req, UserInfoDetails userDetail, BulkCementThreeCityUsageBulletin bulkCementThreeCityUsageBulletin) {
        RegionDTO regionDto = regionsCacheHelper.getByRegionId(userDetail.getRegionId());
        String regionName = regionDto.getRegionName();
        // 单位名称改成了地区
        bulkCementThreeCityUsageBulletin.setUnitName(regionName);
        bulkCementThreeCityUsageBulletin.setYearTarget(req.getYearTarget());
        bulkCementThreeCityUsageBulletin.setPercentageOfAnnualTarget(req.getPercentageOfAnnualTarget());
        bulkCementThreeCityUsageBulletin.setThisMonthUsage(req.getThisMonthUsage());
        bulkCementThreeCityUsageBulletin.setAccumulativeUsage(req.getAccumulativeUsage());
        bulkCementThreeCityUsageBulletin.setGrowthRate(req.getGrowthRate());
        bulkCementThreeCityUsageBulletin.setThisProvinceThisMonthUsage(req.getThisProvinceThisMonthUsage());
        bulkCementThreeCityUsageBulletin.setThisProvinceAccumulativeUsage(req.getThisProvinceAccumulativeUsage());
        bulkCementThreeCityUsageBulletin.setOtherProvinceThisMonthUsage(req.getOtherProvinceThisMonthUsage());
        bulkCementThreeCityUsageBulletin.setOtherProvinceAccumulativeUsage(req.getOtherProvinceAccumulativeUsage());
        bulkCementThreeCityUsageBulletin.setReportMonth(req.getReportMonth());
        bulkCementThreeCityUsageBulletin.setCompanyId(userDetail.getCompanyId());
        bulkCementThreeCityUsageBulletin.setUnitResponsiblePerson(req.getUnitResponsiblePerson());
        bulkCementThreeCityUsageBulletin.setPreparer(req.getPreparer());
        bulkCementThreeCityUsageBulletin.setReviewer(req.getReviewer());
        bulkCementThreeCityUsageBulletin.setSubmissionDate(req.getSubmissionDate());
        bulkCementThreeCityUsageBulletin.setRegionId(userDetail.getRegionId());
        bulkCementThreeCityUsageBulletin.setCreateOn(LocalDateTime.now());
        bulkCementThreeCityUsageBulletin.setCreateBy(userDetail.getUserId());
        bulkCementThreeCityUsageBulletin.setUpdateOn(LocalDateTime.now());
        bulkCementThreeCityUsageBulletin.setUpdateBy(userDetail.getUserId());
    }

    private void checkUploadData(LocalDateTime reportMonth, Long regionId, BulkCementDirectReportSystemDataRelevance cityData) {
        BulkCementThreeCityUsageBulletin bulkCementThreeCityUsageBulletin = bulkCementThreeCityUsageBulletinService.getOne(Wrappers.lambdaQuery(BulkCementThreeCityUsageBulletin.class)
                .eq(BulkCementThreeCityUsageBulletin::getRegionId, regionId)
                .eq(BulkCementThreeCityUsageBulletin::getReportMonth, reportMonth));
        // 判断审核状态，如果审核通过，更新审核通过的数据
        if (Objects.nonNull(bulkCementThreeCityUsageBulletin) &&
                DataUploadAuditStatusEnum.AUDIT_PASS.getCode().equals(bulkCementThreeCityUsageBulletin.getAuditStatus())){
            updateCityData(cityData,bulkCementThreeCityUsageBulletin);
            bulkCementThreeCityUsageBulletinService.removeById(bulkCementThreeCityUsageBulletin);
        }
    }

    private void updateCityData(BulkCementDirectReportSystemDataRelevance cityData, BulkCementThreeCityUsageBulletin bulkCementThreeCityUsageBulletin) {
        if (Objects.nonNull(cityData)) {
            String auditDataIdList = cityData.getAuditDataIdList();
            if (StringUtils.isNotBlank(auditDataIdList)){
                List<Long> idList = Arrays.stream(auditDataIdList.split(StrPool.COMMA)).map(Long::valueOf).collect(Collectors.toList());
                // 将已经存在的该地区该上报月份的数据数据从关联表中删除
                idList.remove(bulkCementThreeCityUsageBulletin.getId());
            }
        }
    }

    public ResBulkCementThreeCityUsageDataUploadDetailVO getBulkCementThreeCityUsageUploadData(ReqBulkCementThreeCityUsageDataUploadPO req) {

        // 获取登录用户信息
        UserInfoDetails userDetail = LoginUserUtil.loginUserDetail();
        // 获取填报的数据
        BigDecimal thisProvinceThisMonthUsage = req.getThisProvinceThisMonthUsage();
        BigDecimal otherProvinceThisMonthUsage = req.getOtherProvinceThisMonthUsage();
        LocalDateTime reportMonth = req.getReportMonth();
        Long regionId = userDetail.getRegionId();

        // 计算合计、本省、外省各数据
        // 获取上个月该地区的散装水泥使用量数据
        LocalDateTime preReportMonth = reportMonth.minusMonths(1L);
        BulkCementThreeCityUsageBulletin preBulkCementThreeCityUsageBulletin = bulkCementThreeCityUsageBulletinService.getOne(Wrappers.lambdaQuery(BulkCementThreeCityUsageBulletin.class)
                .eq(BulkCementThreeCityUsageBulletin::getRegionId, regionId)
                .eq(BulkCementThreeCityUsageBulletin::getReportMonth, preReportMonth));
        VUtils.isTrue(Objects.isNull(preBulkCementThreeCityUsageBulletin)).throwMessage("系统上个月数据不存在!");
        // 获取去年当前上报月份该地区的散装水泥使用量数据
        LocalDateTime preYearReportMonth = preReportMonth.minusYears(1L).plusMonths(1L);
        BulkCementThreeCityUsageBulletin preYearBulkCementThreeCityUsageBulletin = bulkCementThreeCityUsageBulletinService.getOne(Wrappers.lambdaQuery(BulkCementThreeCityUsageBulletin.class)
                .eq(BulkCementThreeCityUsageBulletin::getRegionId, regionId)
                .eq(BulkCementThreeCityUsageBulletin::getReportMonth, preYearReportMonth));
        VUtils.isTrue(Objects.isNull(preYearBulkCementThreeCityUsageBulletin)).throwMessage("系统去年该月数据不存在!");

        ResBulkCementThreeCityUsageDataUploadDetailVO vo = new ResBulkCementThreeCityUsageDataUploadDetailVO();
        vo.setThisProvinceThisMonthUsage(thisProvinceThisMonthUsage);
        vo.setOtherProvinceThisMonthUsage(otherProvinceThisMonthUsage);
        if (Objects.nonNull(thisProvinceThisMonthUsage) && Objects.nonNull(otherProvinceThisMonthUsage)){
            // 本月使用量 = 本省本月使用量 + 外省本月使用量
            // 先取整再运算，防止数据相加再取整后值不一致
            BigDecimal thisProvince = thisProvinceThisMonthUsage.setScale(0, RoundingMode.HALF_UP);
            BigDecimal otherProvince = otherProvinceThisMonthUsage.setScale(0, RoundingMode.HALF_UP);
            BigDecimal thisMonthUsage = thisProvince.add(otherProvince);
            vo.setThisMonthUsage(thisMonthUsage);

            // 累计使用量：上个月的累计使用量 + 本月使用量 = 本省累计使用量 + 外省累计使用量
            BigDecimal preMonthAccumulativeUsage = preBulkCementThreeCityUsageBulletin.getAccumulativeUsage();
            BigDecimal preMonthAccUsage = Objects.isNull(preMonthAccumulativeUsage) ? BigDecimal.ZERO : preMonthAccumulativeUsage;
            BigDecimal accumulativeUsage = thisMonthUsage.add(preMonthAccUsage).setScale(0, RoundingMode.HALF_UP);
            vo.setAccumulativeUsage(accumulativeUsage);

            // 同比增长率: (今年这个月的累计使用量 - 去年这个月的累计使用量) / 去年这个月的累计使用量 * 100
            BigDecimal preYearAccumulativeUsage = preYearBulkCementThreeCityUsageBulletin.getAccumulativeUsage();
            BigDecimal preYearAccUsage = Objects.isNull(preYearAccumulativeUsage) ? BigDecimal.ZERO : preYearAccumulativeUsage;
            BigDecimal growthRate = accumulativeUsage.subtract(preYearAccUsage).divide(preYearAccUsage, 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100L));
            vo.setGrowthRate(growthRate);
        }

        if (Objects.nonNull(thisProvinceThisMonthUsage)) {
            // 本省累计使用量：上个月本省累计使用量 + 本省本月使用量
            BigDecimal preMonthThisProvinceAccumulativeUsage = preBulkCementThreeCityUsageBulletin.getThisProvinceAccumulativeUsage();
            BigDecimal preMonthThisProvinceAccUsage = Objects.isNull(preMonthThisProvinceAccumulativeUsage) ? BigDecimal.ZERO : preMonthThisProvinceAccumulativeUsage;
            BigDecimal thisProvinceAccumulativeUsage = thisProvinceThisMonthUsage.add(preMonthThisProvinceAccUsage).setScale(0, RoundingMode.HALF_UP);
            vo.setThisProvinceAccumulativeUsage(thisProvinceAccumulativeUsage);
        }

        if (Objects.nonNull(otherProvinceThisMonthUsage)) {
            // 外省累计使用量：上个月外省累计使用量 + 外省本月使用量
            BigDecimal preMonthOtherProvinceAccumulativeUsage = preBulkCementThreeCityUsageBulletin.getOtherProvinceAccumulativeUsage();
            BigDecimal preMonthOtherProvinceAccUsage = Objects.isNull(preMonthOtherProvinceAccumulativeUsage) ? BigDecimal.ZERO : preMonthOtherProvinceAccumulativeUsage;
            BigDecimal otherProvinceAccumulativeUsage = otherProvinceThisMonthUsage.add(preMonthOtherProvinceAccUsage).setScale(0, RoundingMode.HALF_UP);
            vo.setOtherProvinceAccumulativeUsage(otherProvinceAccumulativeUsage);
        }
        return vo;
    }

    public BigDecimal getBulkCementThreeCityUsageYearTarget(ReqBulkCementThreeCityUsageDataUploadPO po) {
        LocalDateTime reportMonth = po.getReportMonth();
        VUtils.isTrue(Objects.isNull(reportMonth)).throwMessage("请传入上报月份!");
        Long regionId = po.getRegionId();
        VUtils.isTrue(Objects.isNull(regionId)).throwMessage("请传入区域ID!");
        int year = reportMonth.getYear();
        BulkCementDirectReportSystemUniversalIndex universalIndex = universalIndexService.getOne(Wrappers.lambdaQuery(BulkCementDirectReportSystemUniversalIndex.class)
                .eq(BulkCementDirectReportSystemUniversalIndex::getRegionId, regionId)
                .eq(BulkCementDirectReportSystemUniversalIndex::getYear, year));

        if (Objects.isNull(universalIndex)){
            return BigDecimal.ZERO;
        }
        return universalIndex.getBulkCementUsageYearTarget();
    }
}
