/*
 * 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 vip.xiaonuo.biz.modular.depotGrainInfoWarn.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.xiaonuo.biz.core.Const.BizStr;
import vip.xiaonuo.biz.modular.depotAlarm.service.DepotAlarmService;
import vip.xiaonuo.biz.modular.depotGrain.service.DepotGrainService;
import vip.xiaonuo.biz.modular.depotGrainInfo.entity.DepotGrainInfo;
import vip.xiaonuo.biz.modular.depotGrainInfo.param.DepotGrainInfoPageParam;
import vip.xiaonuo.biz.modular.depotGrainInfo.service.DepotGrainInfoService;
import vip.xiaonuo.biz.modular.depotGrainInfoPrice.entity.DepotGrainInfoPrice;
import vip.xiaonuo.biz.modular.depotGrainInfoWarn.param.*;
import vip.xiaonuo.common.enums.CommonSortOrderEnum;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.common.page.CommonPageRequest;
import vip.xiaonuo.biz.modular.depotGrainInfoWarn.entity.DepotGrainInfoWarn;
import vip.xiaonuo.biz.modular.depotGrainInfoWarn.mapper.DepotGrainInfoWarnMapper;
import vip.xiaonuo.common.util.BigDecimalUtil;
import vip.xiaonuo.common.util.DatesUtil;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 客户预警处理Service接口实现类
 *
 * @author xiang
 * @date 2023/09/14 16:20
 **/
@Service
public class DepotGrainInfoWarnService extends ServiceImpl<DepotGrainInfoWarnMapper, DepotGrainInfoWarn> {

    @Resource
    DepotGrainService depotGrainService;
    @Resource
    DepotGrainInfoService depotGrainInfoService;
    @Resource
    DepotAlarmService alarmService;

    public Page<DepotGrainInfoWarn> page(DepotGrainInfoWarnPageParam param) {
        QueryWrapper<DepotGrainInfoWarn> wrapper = new QueryWrapper<>();
        List<String> depotIdLst = depotGrainService.lstOrgGrep();
        wrapper.lambda().in(CollUtil.isNotEmpty(depotIdLst), DepotGrainInfoWarn::getDepotId, depotIdLst);
        if (ObjectUtil.isNotEmpty(param.getDepotId())) {
            wrapper.lambda().eq(DepotGrainInfoWarn::getDepotId, param.getDepotId());
        }
        wrapper.lambda().eq(Strings.isNotBlank(param.getSaveState()), DepotGrainInfoWarn::getSaveState, param.getSaveState());
        wrapper.lambda().eq(Strings.isNotBlank(param.getWarnType()), DepotGrainInfoWarn::getWarnType, param.getWarnType());
        wrapper.lambda().like(Strings.isNotBlank(param.getWarnMsg()), DepotGrainInfoWarn::getWarnMsg, param.getWarnMsg());
        if (ObjectUtil.isAllNotEmpty(param.getSortField(), param.getSortOrder())) {
            CommonSortOrderEnum.validate(param.getSortOrder());
            wrapper.orderBy(true, param.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()),
                    StrUtil.toUnderlineCase(param.getSortField()));
        } else {
            wrapper.lambda().orderByDesc(DepotGrainInfoWarn::getId);
        }
        Page page = this.page(CommonPageRequest.defaultPage(), wrapper);
        //匹配粮库名称
        depotGrainService.putDepotName(page.getRecords());
        return page;
    }

    public List<DepotGrainInfoWarn> lst(DepotGrainInfoWarn param) {
        return list(new LambdaQueryWrapper<>(param));
    }

    public DepotGrainInfoWarn getOne(DepotGrainInfoWarn param) {
        return getOne(new LambdaQueryWrapper<>(param));
    }

    public void add(DepotGrainInfoWarnAddParam param) {
        DepotGrainInfoWarn infoWarn = BeanUtil.toBean(param, DepotGrainInfoWarn.class);
        this.save(infoWarn);
    }

    @Transactional(rollbackFor = Exception.class)
    public void adds(List<DepotGrainInfoWarn> warns) {
        if (warns.isEmpty()) return;
        alarmService.addByGrainInfoWarn(warns);
        this.saveOrUpdateBatch(warns);
    }

    public void edit(DepotGrainInfoWarnEditParam depotGrainInfoWarnEditParam) {
        DepotGrainInfoWarn depotGrainInfoWarn = this.queryEntity(depotGrainInfoWarnEditParam.getId());
        BeanUtil.copyProperties(depotGrainInfoWarnEditParam, depotGrainInfoWarn);
        this.updateById(depotGrainInfoWarn);
    }

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

    public DepotGrainInfoWarn detail(DepotGrainInfoWarnIdParam depotGrainInfoWarnIdParam) {
        return this.queryEntity(depotGrainInfoWarnIdParam.getId());
    }

    public DepotGrainInfoWarn queryEntity(String id) {
        DepotGrainInfoWarn depotGrainInfoWarn = this.getById(id);
        if (ObjectUtil.isEmpty(depotGrainInfoWarn)) {
            throw new CommonException("客户预警处理不存在，id值为：{}", id);
        }
        return depotGrainInfoWarn;
    }

    /**
     * 价格预警
     * 关于平均价格标黄和标红的设定。
     * 每一个户都有一个加权的平均质押价格，
     * 我们会定期更新几个主要产区的主流价格，
     * 然后每一个户根据他所在地在录入贷前信息时，
     * 就关联上离的最近的这个产区主流价格。
     * 当主流价格低于平均质押价格5%时，平均价格标黄；
     * 低于10%时，标红。
     *
     * @param info 种类信息
     * @author xiang
     * @date 2023/09/14 15:00
     **/
    @Transactional(rollbackFor = Exception.class)
    public void loanPriceWarn(DepotGrainInfoPrice info) {
        if (BigDecimalUtil.isNullOrEqZero(info.getZonePrice())) return;
        List<DepotGrainInfoWarn> warns = new ArrayList<>();
        DepotGrainInfoWarn warn = getOne(new DepotGrainInfoWarn(info.getDepotId(), info.getGrainGroup(), BizStr.STATE_PROCESS_N));
        if (info.getZonePrice().compareTo(info.getLoanPriceAvg().multiply(new BigDecimal("0.95"))) < 0) {
            if (warn == null)
                warn = new DepotGrainInfoWarn(info.getDepotId(), info.getGrainGroup(), BizStr.STATE_PROCESS_N);
            String warnPriceLevel = BizStr.COLOR_YELLOW;
            if (info.getZonePrice().compareTo(info.getLoanPriceAvg().multiply(new BigDecimal("0.9"))) < 0) {
                warnPriceLevel = BizStr.COLOR_RED;
            }
            String differencePrice = info.getLoanPriceAvg().subtract(info.getZonePrice()).divide(info.getLoanPriceAvg(), 4, BigDecimal.ROUND_HALF_UP).movePointRight(2) + "%";
            String msg = String.format("%s 主流价格(%s)低于平均质押价格(%s) %s", info.getGrainGroup(), info.getZonePrice(), info.getLoanPriceAvg(), differencePrice);
            warn.setLoanPrice(info.getLoanPriceAvg());
            warn.setZonePrice(info.getZonePrice());
            warn.setWarnColourLevel(warnPriceLevel);
            warn.setWarnType(BizStr.WARN_TYPE_PRICE);
            warn.setWarnMsg(msg);
        } else if (warn != null) {
            warn.setSaveState(BizStr.STATE_PROCESS_Y);
        } else {
            return;
        }
        warns.add(warn);
        adds(warns);
    }

    /**
     * 贷款合同到期日预警
     * 距贷款到期日1个月时，该企业贷款到期日标黄；
     * 距到期日15天时，标红。
     *
     * @author xiang
     * @date 2023/09/14 15:00
     **/
    @Transactional(rollbackFor = Exception.class)
    public void loanDateWarns(String depotId) {
        //已有
        List<DepotGrainInfoWarn> dbs = lst(new DepotGrainInfoWarn(depotId, null, BizStr.STATE_PROCESS_N, BizStr.WARN_TYPE_DATE));
        List<String> dbDepotIds = dbs.stream().map(DepotGrainInfoWarn::getDepotId).collect(Collectors.toList());
        for (DepotGrainInfoWarn one : dbs) {
            one.setSaveState(BizStr.STATE_PROCESS_Y);
        }
        //客户风险信息
        List<DepotGrainInfo> grainInfos = depotGrainInfoService.lst(new DepotGrainInfoPageParam(depotId, false));
        String nowDate = DatesUtil.forDate();
        Date nextMonth = DateUtil.nextMonth();
        grainInfos = grainInfos.stream().filter(g -> nextMonth.compareTo(DatesUtil.forDate(g.getLoanEndDate())) > 0).collect(Collectors.toList());
        //风险
        List<DepotGrainInfoWarn> warns = new ArrayList<>(grainInfos.size());
        for (DepotGrainInfo grainInfo : grainInfos) {
            int dateCount = DatesUtil.differentDaysByMillisecond(nowDate, grainInfo.getLoanEndDate());
            String msg = String.format("贷款日%s距离合同到期日%s还剩%s天。", nowDate, grainInfo.getLoanEndDate(), dateCount);
            if (dateCount < 0)
                msg = msg.replace("还剩-", "过期");
            DepotGrainInfoWarn addParam = new DepotGrainInfoWarn(grainInfo.getDepotId(), nowDate
                    , grainInfo.getLoanEndDate(), dateCount < 16 ? BizStr.COLOR_RED : BizStr.COLOR_YELLOW, msg);
            //已有则更新
            if (dbDepotIds.contains(grainInfo.getDepotId())) {
                for (DepotGrainInfoWarn one : dbs) {
                    if (!Objects.equals(one.getDepotId(), grainInfo.getDepotId())) continue;
                    addParam.setId(one.getId());
                    addParam.setUnionAlarmId(one.getUnionAlarmId());
                    BeanUtil.copyProperties(addParam, one);
                    break;
                }
            }
            //没有则新增
            else {
                warns.add(addParam);
            }
        }
        //保存
        dbs.addAll(warns);
        this.adds(dbs);
    }

    public void loanDateWarns() {
        loanDateWarns(null);
    }

}
