/*
 * Copyright [2022] [https://www.xiaonuo.vip]
 *
 * Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：
 *
 * 1.请不要删除和修改根目录下的LICENSE文件。
 * 2.请不要删除和修改Snowy源码头部的版权声明。
 * 3.本项目代码可免费商业使用，商业使用请保留源码和相关描述文件的项目出处，作者声明等。
 * 4.分发源码时候，请注明软件出处 https://www.xiaonuo.vip
 * 5.不可二次分发开源参与同类竞品，如有想法可联系团队xiaonuobase@qq.com商议合作。
 * 6.若您的项目无法满足以上几点，需要更多功能代码，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package com.unis.basic.info.modular.grainPriceCollectProvinceSum.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.unis.basic.info.modular.grainPriceCollectCategory.entity.GrainPriceCollectCategory;
import com.unis.basic.info.modular.grainPriceCollectCategory.enums.GrainPriceCollectTypeEnum;
import com.unis.basic.info.modular.grainPriceCollectCategory.service.GrainPriceCollectCategoryService;
import com.unis.basic.info.modular.grainPriceCollectCitySum.param.SummaryAnalysisParam;
import com.unis.basic.info.modular.grainPriceCollectProvinceSum.entity.GrainPriceCollectProvinceSum;
import com.unis.basic.info.modular.grainPriceCollectProvinceSum.mapper.GrainPriceCollectProvinceSumMapper;
import com.unis.basic.info.modular.grainPriceCollectProvinceSum.param.GrainPriceCollectProvinceSumAddParam;
import com.unis.basic.info.modular.grainPriceCollectProvinceSum.param.GrainPriceCollectProvinceSumEditParam;
import com.unis.basic.info.modular.grainPriceCollectProvinceSum.param.GrainPriceCollectProvinceSumIdParam;
import com.unis.basic.info.modular.grainPriceCollectProvinceSum.param.GrainPriceCollectProvinceSumPageParam;
import com.unis.basic.info.modular.grainPriceCollectProvinceSum.service.GrainPriceCollectProvinceSumService;
import com.unis.common.enums.CommonSortOrderEnum;
import com.unis.common.exception.CommonException;
import com.unis.common.page.CommonPageRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 省级粮食价格采集汇总Service接口实现类
 *
 * @author TS
 * @date  2024/04/03 10:39
 **/
@Service
public class GrainPriceCollectProvinceSumServiceImpl extends ServiceImpl<GrainPriceCollectProvinceSumMapper, GrainPriceCollectProvinceSum> implements GrainPriceCollectProvinceSumService {

    @Resource
    private GrainPriceCollectProvinceSumMapper grainPriceCollectProvinceSumMapper;
    @Autowired
    private GrainPriceCollectCategoryService grainPriceCollectCategoryService;

    @Override
    public Page<GrainPriceCollectProvinceSum> page(GrainPriceCollectProvinceSumPageParam grainPriceCollectProvinceSumPageParam) {
        QueryWrapper<GrainPriceCollectProvinceSum> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isAllNotEmpty(grainPriceCollectProvinceSumPageParam.getSortField(), grainPriceCollectProvinceSumPageParam.getSortOrder())) {
            CommonSortOrderEnum.validate(grainPriceCollectProvinceSumPageParam.getSortOrder());
            queryWrapper.orderBy(true, grainPriceCollectProvinceSumPageParam.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()),
                    StrUtil.toUnderlineCase(grainPriceCollectProvinceSumPageParam.getSortField()));
        } else {
            queryWrapper.lambda().orderByAsc(GrainPriceCollectProvinceSum::getId);
        }
        return this.page(CommonPageRequest.defaultPage(), queryWrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(GrainPriceCollectProvinceSumAddParam grainPriceCollectProvinceSumAddParam) {
        GrainPriceCollectProvinceSum grainPriceCollectProvinceSum = BeanUtil.toBean(grainPriceCollectProvinceSumAddParam, GrainPriceCollectProvinceSum.class);
        this.save(grainPriceCollectProvinceSum);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(GrainPriceCollectProvinceSumEditParam grainPriceCollectProvinceSumEditParam) {
        GrainPriceCollectProvinceSum grainPriceCollectProvinceSum = this.queryEntity(grainPriceCollectProvinceSumEditParam.getId());
        BeanUtil.copyProperties(grainPriceCollectProvinceSumEditParam, grainPriceCollectProvinceSum);
        this.updateById(grainPriceCollectProvinceSum);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<GrainPriceCollectProvinceSumIdParam> grainPriceCollectProvinceSumIdParamList) {
        // 执行删除
        this.removeByIds(CollStreamUtil.toList(grainPriceCollectProvinceSumIdParamList, GrainPriceCollectProvinceSumIdParam::getId));
    }

    @Override
    public GrainPriceCollectProvinceSum detail(GrainPriceCollectProvinceSumIdParam grainPriceCollectProvinceSumIdParam) {
        return this.queryEntity(grainPriceCollectProvinceSumIdParam.getId());
    }

    @Override
    public GrainPriceCollectProvinceSum queryEntity(String id) {
        GrainPriceCollectProvinceSum grainPriceCollectProvinceSum = this.getById(id);
        if (ObjectUtil.isEmpty(grainPriceCollectProvinceSum)) {
            throw new CommonException("省级粮食价格采集汇总不存在，id值为：{}", id);
        }
        return grainPriceCollectProvinceSum;
    }

    /**
     * 省级粮食价格采集汇总
     *
     * @param orgId
     * @param userId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String collectProvinceSum(String orgId, String userId) {
        //得到当前周的周一时间,周末时间
        // 获取当前周一
        String monday = DateUtil.beginOfWeek(new Date()).toStringDefaultTimeZone();
        // 获取当前周日
        String sunday = DateUtil.endOfWeek(new Date()).toStringDefaultTimeZone();
        //查询是否汇总
        QueryWrapper<GrainPriceCollectProvinceSum> queryWrapper = new QueryWrapper<>();
        queryWrapper.between("sum_time", monday, sunday);
        List<GrainPriceCollectProvinceSum> grainPriceCollectCitySums = this.list(queryWrapper);
        if (grainPriceCollectCitySums.size() > 0) {
            throw new CommonException("在当前期间内,本单位已汇总");
        }
        //得到每个监测点已审核通过数据,只要有一个站点未审核通过,就不能汇总
        //表示有未审核通过监测点,在当前期间内
        List<Map<String, Object>> orgUploads = grainPriceCollectProvinceSumMapper.getOrgUploads("0", monday, sunday);
        if (orgUploads != null && orgUploads.size() > 0) {
            String str1 = "";
            String str2 = "";
            for (int i = 0; i < orgUploads.size(); i++) {
                Map<String, Object> map = orgUploads.get(i);
                String status = (String) map.getOrDefault("status", "-1");
                if (StringUtils.equals(status, "-1")) { //未汇总单位
                    str1 += map.getOrDefault("orgName", "") + ",";
                } else { //未上报单位
                    str2 += map.getOrDefault("orgName", "") + ",";
                }
            }
//            throw new CommonException("未汇总单位:{};未上报单位:{}",str1,str2);
        }
        //处理当前期间的上报数据
        // 以所有下级单位汇总后上报数据进行汇总，如果有一个单位未汇总止报，则不能汇总
        //默认汇总本期间数据（当前周）
        //保存汇总主表信息
        GrainPriceCollectProvinceSum citySum = new GrainPriceCollectProvinceSum();
        citySum.setSysUserId(userId);
        citySum.setSumTime(new Date());
        //汇总期数：当年汇总数+1
        Integer countPeriod = getCountPeriod();
        citySum.setCountPeriod(countPeriod); //
        if (!this.save(citySum)) {
            throw new CommonException("保存省级汇总信息失败");
        }
        String id = citySum.getId();
        List<Map<String, Object>> prictTypes = grainPriceCollectProvinceSumMapper.getAvgPriceByCity(GrainPriceCollectTypeEnum.CitySum.getValue(), monday, sunday);
        if (prictTypes == null || prictTypes.size() <= 0) {
            throw new CommonException("未有市州汇总上报数据");
        }
        DateTime offWeek = DateUtil.offsetWeek(new Date(), -1);
        // 获取上周周一
        String offMonday = DateUtil.beginOfWeek(offWeek).toStringDefaultTimeZone();
        // 获取上前周日
        String offSunday = DateUtil.endOfWeek(offWeek).toStringDefaultTimeZone();

        //取得上月的当前天
        DateTime offMonthDay = DateUtil.offsetMonth(new Date(), -1);
        // 获取上月当前天所处周一
        String offMonthCurMonday = DateUtil.beginOfWeek(offMonthDay).toStringDefaultTimeZone();
        // 获取上月当前天所处周日
        String offMonthCurSunday = DateUtil.endOfWeek(offMonthDay).toStringDefaultTimeZone();

        // 获取上月当前天上周所处周一
        String offMonthOffMonday = DateUtil.beginOfWeek(DateUtil.offsetWeek(offMonthDay, -1)).toStringDefaultTimeZone();
        // 获取上月当前天上周所处周日
        String offMonthOffSunday = DateUtil.endOfWeek(DateUtil.offsetWeek(offMonthDay, -1)).toStringDefaultTimeZone();

        // 获取上月当前天下周所处周一
        String offMonthNextMonday = DateUtil.beginOfWeek(DateUtil.offsetWeek(offMonthDay, 1)).toStringDefaultTimeZone();
        // 获取上月当前天下周所处周日
        String offMonthNextSunday = DateUtil.endOfWeek(DateUtil.offsetWeek(offMonthDay, 1)).toStringDefaultTimeZone();

        //取得去年的当前天
        DateTime offYearDay = DateUtil.offsetMonth(new Date(), -12);
        // 获取去年当前天所处周一
        String offYearCurMonday = DateUtil.beginOfWeek(offYearDay).toStringDefaultTimeZone();
        // 获取去年当前天所处周日
        String offYearCurSunday = DateUtil.endOfWeek(offYearDay).toStringDefaultTimeZone();

        // 获取去年当前天上周所处周一
        String offYearOffMonday = DateUtil.beginOfWeek(DateUtil.offsetWeek(offYearDay, -1)).toStringDefaultTimeZone();
        // 获取去年当前天上周所处周日
        String offYearOffSunday = DateUtil.endOfWeek(DateUtil.offsetWeek(offYearDay, -1)).toStringDefaultTimeZone();

        // 获取去年当前天下周所处周一
        String offYearNextMonday = DateUtil.beginOfWeek(DateUtil.offsetWeek(offYearDay, 1)).toStringDefaultTimeZone();
        // 获取去年当前天下周所处周日
        String offYearNextSunday = DateUtil.endOfWeek(DateUtil.offsetWeek(offYearDay, 1)).toStringDefaultTimeZone();


        //保存市级汇总从表信息
        List<GrainPriceCollectCategory> categoryList = new ArrayList<>();
        for (int i = 0; i < prictTypes.size(); i++) {
            Map<String, Object> map = prictTypes.get(i);
            GrainPriceCollectCategory category = new GrainPriceCollectCategory();
            category.setType(Integer.parseInt(GrainPriceCollectTypeEnum.ProvinceSum.getValue()));
            category.setTypeId(id);
            category.setFirstLevel(NumberUtil.parseInt(map.get("firstLevel").toString()));
            category.setSecondLevel(NumberUtil.parseInt(map.get("secondLevel").toString()));
            category.setThreeLevel(NumberUtil.parseInt(map.get("threeLevel").toString()));
            category.setPriceType(NumberUtil.parseInt(map.get("priceType").toString()));
            category.setPrice(NumberUtil.toBigDecimal(map.get("avgPrice").toString()));
            //得到本期价格
            BigDecimal avgPrice = category.getPrice();

            //上一期间与前期间进行比较，现在默认一周为一期间
            List<Map<String, Object>> categoryList1 = grainPriceCollectProvinceSumMapper.getOffAvgPriceByProvince(category.getType().toString(), offMonday, offSunday,
                    category.getPriceType().toString(),
                    category.getFirstLevel().toString(),
                    category.getSecondLevel().toString(),
                    category.getThreeLevel().toString()
            );
            //未查到数据表示上月上一期间没有数据
            BigDecimal offAvgPrice = NumberUtil.toBigDecimal("0.00");
            if (categoryList1.size() == 1) {
                //得到上一期间价格
                offAvgPrice = NumberUtil.toBigDecimal(categoryList1.get(0).get("offAvgPrice").toString());
            } else { //暂时不进行设置

            }
            //与上周同期比 =（本期间平价价格-上期间平价价格）/本期间平价价格
            BigDecimal weekRate = NumberUtil.div(NumberUtil.sub(avgPrice, offAvgPrice), avgPrice);
            category.setWeekRate(weekRate);


            //处理上月
            categoryList1 = grainPriceCollectProvinceSumMapper.getOffAvgPriceByProvince(category.getType().toString(), offMonthCurMonday, offMonthCurSunday,
                    category.getPriceType().toString(),
                    category.getFirstLevel().toString(),
                    category.getSecondLevel().toString(),
                    category.getThreeLevel().toString()
            );
            //未查到数据表示上一期间没有数据，则按平价价格为0计算
            BigDecimal offMonthAvgPrice = NumberUtil.toBigDecimal("0.00");
            if (categoryList1.size() == 1) {
                //得到上月同一期间价格
                offMonthAvgPrice = NumberUtil.toBigDecimal(categoryList1.get(0).get("offAvgPrice").toString());
            } else {
                categoryList1 = grainPriceCollectProvinceSumMapper.getOffAvgPriceByProvince(category.getType().toString(), offMonthOffMonday, offMonthOffSunday,
                        category.getPriceType().toString(),
                        category.getFirstLevel().toString(),
                        category.getSecondLevel().toString(),
                        category.getThreeLevel().toString()
                );
                if (categoryList1.size() == 1) {
                    //得到上月上一期间价格
                    offMonthAvgPrice = NumberUtil.toBigDecimal(categoryList1.get(0).get("offAvgPrice").toString());
                } else {
                    categoryList1 = grainPriceCollectProvinceSumMapper.getOffAvgPriceByProvince(category.getType().toString(), offMonthNextMonday, offMonthNextSunday,
                            category.getPriceType().toString(),
                            category.getFirstLevel().toString(),
                            category.getSecondLevel().toString(),
                            category.getThreeLevel().toString()
                    );

                    if (categoryList1.size() == 1) {
                        //得到上月下一期间价格
                        offMonthAvgPrice = NumberUtil.toBigDecimal(categoryList1.get(0).get("offAvgPrice").toString());
                    }
                }
            }
            //与上月同期比 =（本期间平价价格-上月期间平价价格）/本期间平价价格
            BigDecimal monthRate = NumberUtil.div(NumberUtil.sub(avgPrice, offMonthAvgPrice), avgPrice);
            category.setMonthRate(monthRate);

            //处理上年
            categoryList1 = grainPriceCollectProvinceSumMapper.getOffAvgPriceByProvince(category.getType().toString(), offYearCurMonday, offYearCurSunday,
                    category.getPriceType().toString(),
                    category.getFirstLevel().toString(),
                    category.getSecondLevel().toString(),
                    category.getThreeLevel().toString()
            );
            //未查到数据表示上一期间没有数据，则按平价价格为0计算
            BigDecimal offYearAvgPrice = NumberUtil.toBigDecimal("0.00");
            if (categoryList1.size() == 1) {
                //得到去年同一期间价格
                offYearAvgPrice = NumberUtil.toBigDecimal(categoryList1.get(0).get("offAvgPrice").toString());
            } else {
                categoryList1 = grainPriceCollectProvinceSumMapper.getOffAvgPriceByProvince(category.getType().toString(), offYearOffMonday, offYearOffSunday,
                        category.getPriceType().toString(),
                        category.getFirstLevel().toString(),
                        category.getSecondLevel().toString(),
                        category.getThreeLevel().toString()
                );
                if (categoryList1.size() == 1) {
                    //得到上年上一期间价格
                    offYearAvgPrice = NumberUtil.toBigDecimal(categoryList1.get(0).get("offAvgPrice").toString());
                } else {
                    categoryList1 = grainPriceCollectProvinceSumMapper.getOffAvgPriceByProvince(category.getType().toString(), offYearNextMonday, offYearNextSunday,
                            category.getPriceType().toString(),
                            category.getFirstLevel().toString(),
                            category.getSecondLevel().toString(),
                            category.getThreeLevel().toString()
                    );
                    if (categoryList1.size() == 1) {
                        //得到上年下一期间价格
                        offYearAvgPrice = NumberUtil.toBigDecimal(categoryList1.get(0).get("offAvgPrice").toString());
                    }
                }
            }
            //与上年同期比 =（本期间平价价格-上月期间平价价格）/本期间平价价格
            BigDecimal yearRate = NumberUtil.div(NumberUtil.sub(avgPrice, offYearAvgPrice), avgPrice);
            category.setYearRate(yearRate);
            categoryList.add(category);
        }
        if (!grainPriceCollectCategoryService.saveBatch(categoryList)) {
            throw new CommonException("保存省级汇明细总信息失败");
        }
        //通过条件修改市级价格采集汇总对应的省级汇总表Id
        grainPriceCollectProvinceSumMapper.updateGrainPriceCollectCitySum(orgId,id,monday,sunday);
        return "保存成功";
    }

    /**
     * 获取自定义省级粮食价格采集汇总分页
     *
     * @param pageParam
     * @return
     */
    @Override
    public IPage<Map<String, Object>> findPage(GrainPriceCollectProvinceSumPageParam pageParam) {
        //条形查询器
        QueryWrapper<GrainPriceCollectProvinceSum> queryWrapper = new QueryWrapper<>();
        //分页相关
        if (pageParam.getCountPeriod() != null && pageParam.getCountPeriod() > 0) {
            queryWrapper.eq("a.count_period", pageParam.getCountPeriod());
        }
        if (StringUtils.isNotBlank(pageParam.getSumEndTime()) && StringUtils.isNotBlank(pageParam.getSumEndTime())) {
            queryWrapper.apply(" DATE_FORMAT(ifnull(a.sum_time,NOW()),'%Y-%m-%d') >=  '" + pageParam.getSumStartTime() + "' AND DATE_FORMAT(ifnull(a.sum_time,NOW()),'%Y-%m-%d') <= '" + pageParam.getSumEndTime() + " 23:59:59'");

        }
        Page<GrainPriceCollectProvinceSum> p = new Page<>(pageParam.getCurrent(), pageParam.getSize());

        IPage<Map<String, Object>> page = grainPriceCollectProvinceSumMapper.selectMyMapsPage(p, queryWrapper);
        return page;
    }

    /**
     * 汇总期数：当年汇总数+1
     *
     * @return
     */
    private Integer getCountPeriod() {

        //今年第一天
        String firstDayOfYear = DateUtil.beginOfYear(new Date()).toStringDefaultTimeZone();
        //今年最后一天
        String endDayOfYear = DateUtil.endOfYear(new Date()).toStringDefaultTimeZone();
        QueryWrapper<GrainPriceCollectProvinceSum> queryWrapper = new QueryWrapper<>();
        queryWrapper.between("sum_time", firstDayOfYear, endDayOfYear);
        queryWrapper.orderByDesc("sum_time");
        queryWrapper.last("limit 0,1");
        GrainPriceCollectProvinceSum grainPriceCollectCitySum = this.getOne(queryWrapper, false);
        if (grainPriceCollectCitySum != null && grainPriceCollectCitySum.getCountPeriod() > 0) {
            return grainPriceCollectCitySum.getCountPeriod() + 1;
        }
        return 1;
    }

    @Override
    public List<GrainPriceCollectProvinceSum> summaryAnalysis(SummaryAnalysisParam summaryAnalysisParam) {
        {
            QueryWrapper<GrainPriceCollectProvinceSum> queryWrapper = new QueryWrapper<>();
            if (ObjectUtil.isAllNotEmpty(summaryAnalysisParam.getSumStartTime(), summaryAnalysisParam.getSumEndTime())) {
                queryWrapper.between("sum_time", summaryAnalysisParam.getSumStartTime(), summaryAnalysisParam.getSumEndTime());
            }
            queryWrapper.orderByAsc("sum_time");
            List<GrainPriceCollectProvinceSum> provinceList = grainPriceCollectProvinceSumMapper.selectList(queryWrapper);
            if (ObjectUtil.isNull(summaryAnalysisParam.getSysOrgId()) && provinceList.size() > 0) {//省级粮食价格采集汇总
                for (GrainPriceCollectProvinceSum grainPriceCollectProvinceSum : provinceList) {
                    QueryWrapper<GrainPriceCollectCategory> queryWrapperZ = new QueryWrapper<>();
                    queryWrapperZ.eq("type_id", grainPriceCollectProvinceSum.getId());
                    queryWrapperZ.eq("type", 3);//省级粮食价格采集汇总
                    if (summaryAnalysisParam.getFirstLevel().equals(1)) {//一级分类 1：原粮；2：杂粮；3：成品粮；4：省级储备
                        if (ObjectUtil.isNotNull(summaryAnalysisParam.getSecondLevel())) {
                            queryWrapperZ.eq("second_level", summaryAnalysisParam.getSecondLevel());
                        }
                        queryWrapperZ.eq("price_type", 1);//价格类型 1：收购价；2：入库价；3：出库价；4：出厂价；5：批发价；6：零售价；
                        queryWrapperZ.eq("first_level", 1);
                    }
                    if (summaryAnalysisParam.getFirstLevel().equals(3)) {//一级分类 1：原粮；2：杂粮；3：成品粮；4：省级储备
                        if (ObjectUtil.isNotNull(summaryAnalysisParam.getThreeLevel())) {
                            queryWrapperZ.eq("three_level", summaryAnalysisParam.getThreeLevel());
                        }
                        //queryWrapperZ.eq("price_type",5).or().eq("price_type",6);
                        queryWrapperZ.le("price_type", 6);
                        queryWrapperZ.ge("price_type", 5);
                        queryWrapperZ.eq("first_level", 3);
                    }
                    if (summaryAnalysisParam.getFirstLevel().equals(4)) {//一级分类 1：原粮；2：杂粮；3：成品粮；4：省级储备
                        if (ObjectUtil.isNotNull(summaryAnalysisParam.getSecondLevel())) {
                            queryWrapperZ.eq("second_level", summaryAnalysisParam.getSecondLevel());
                        }
                        //queryWrapperZ.eq("price_type",2).or().eq("price_type",3);
                        queryWrapperZ.le("price_type", 3);
                        queryWrapperZ.ge("price_type", 2);
                        queryWrapperZ.eq("first_level", 4);
                    }
                    List<GrainPriceCollectCategory> zList = grainPriceCollectCategoryService.list(queryWrapperZ);
                    grainPriceCollectProvinceSum.setCollectCategoryList(zList);
                }
            }
            return provinceList;
        }
    }
}