package cn.com.ty.lift.batch.applet.service;

import cn.com.ty.lift.batch.applet.constants.DataStatisticsConstants;
import cn.com.ty.lift.batch.applet.dao.mapper.PaymentDataMapper;
import cn.com.ty.lift.batch.applet.dao.model.PaymentDataModel;
import cn.com.ty.lift.batch.applet.dao.model.request.CommonRequest;
import cn.com.ty.lift.batch.applet.dao.model.request.PaymentDataRequest;
import cn.com.ty.lift.batch.applet.dao.model.response.ProjectPaymentResponse;
import cn.com.ty.lift.batch.applet.dao.model.response.RegionPaymentResponse;
import cn.com.ty.lift.batch.applet.util.DataStatisticsUtil;
import cn.com.ty.lift.common.constants.ApiConstants;
import cn.com.ty.lift.common.utils.ProjectUtils;
import cn.com.xwy.boot.web.dto.RestResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author huangyuan
 * @date 2020/2/3
 * @description
 */
@Service
public class PaymentDataService {

    @Resource
    private PaymentDataMapper paymentDataMapper;

    @Resource
    private RedisTemplate redisTemplate;

    /**
     * @param commonRequest 起始时间 结束时间
     * @return
     * @description 将收款数据放入redis中
     * @date 2020/2/4 2:20 下午
     */
    public void putPaymentDataToRedis(CommonRequest commonRequest) {
        List<PaymentDataModel> paymentDataModelList = paymentDataMapper.getPaymentDataList(commonRequest);
        //将收款数据放入redis中
        DataStatisticsUtil.putStatisticsDataToRedis(paymentDataModelList, redisTemplate,
                DataStatisticsConstants.PAYMENT_DATA_FIELD);
    }

    /**
     * @param paymentDataRequest
     * @return
     * @description 从redis中获取收款数据
     * @date 2020/2/4 2:30 下午
     */
    public List<PaymentDataModel> getPaymentDataListFromRedis(PaymentDataRequest paymentDataRequest) {
        //从redis中获取当前公司的收款数据
        List<PaymentDataModel> paymentDataModelList = (List<PaymentDataModel>)
                DataStatisticsUtil.getStatisticsDataFromRedis(redisTemplate,
                        DataStatisticsConstants.PAYMENT_DATA_FIELD, paymentDataRequest.getMtCompanyId());
        if (paymentDataModelList != null && paymentDataModelList.size() > 0) {
            //通过终止时间过滤
            if (paymentDataRequest.getEndDate() != null) {
                paymentDataModelList = paymentDataModelList.stream()
                        .filter(a -> {
                            if (a.getPlanDate() != null) {
                                return a.getPlanDate().isBefore(paymentDataRequest.getEndDate());
                            }
                            return false;
                        })
                        .collect(Collectors.toList());
            }
            //通过起始时间过滤
            if (paymentDataRequest.getStartDate() != null) {
                paymentDataModelList = paymentDataModelList.stream()
                        .filter(a -> {
                            if (a.getPlanDate() != null) {
                                return a.getPlanDate().isAfter(paymentDataRequest.getStartDate());
                            }
                            return false;
                        })
                        .collect(Collectors.toList());
            }
            //通过合同类型过滤
            if (paymentDataRequest.getPaymentType() != null) {
                paymentDataModelList = paymentDataModelList.stream()
                        .filter(a -> {
                            if (a.getPaymentType() != null) {
                                return a.getPaymentType() == paymentDataRequest.getPaymentType();
                            }
                            return false;
                        })
                        .collect(Collectors.toList());
            }
        }
        return paymentDataModelList;
    }

    /**
     * @param
     * @return
     * @description 收款数据总览
     * @date 2020/2/5 4:55 下午
     */
    public RestResponse paymentOverView(PaymentDataRequest paymentDataRequest) {
        Map<Integer, Double> paymentStatusToMoney = DataStatisticsConstants.PAYMENT_STATUS_TO_MONEY;
        List<PaymentDataModel> paymentDataModelList = getPaymentDataListFromRedis(paymentDataRequest);
        if (paymentDataModelList != null && paymentDataModelList.size() > 0) {
            //计划收款总和
            double totalPlanMoney = paymentDataModelList.stream().mapToDouble(
                    paymentDataModel -> DataStatisticsUtil.getDoubleValue(paymentDataModel.getPlanMoney())
            ).sum();
            //实际收款总和
            double totalWorkMoney = paymentDataModelList.stream().mapToDouble(
                    paymentDataModel -> DataStatisticsUtil.getDoubleValue(paymentDataModel.getWorkMoney())
            ).sum();
            //超期未收总和
            double totalBeyondMoney = totalPlanMoney - totalWorkMoney;
            paymentStatusToMoney.put(1, totalPlanMoney);
            paymentStatusToMoney.put(2, totalWorkMoney);
            paymentStatusToMoney.put(3, totalBeyondMoney);
        }
        return RestResponse.success(ProjectUtils.transReturnMapToStatisticsKVModel(paymentStatusToMoney), ApiConstants.RESULT_SUCCESS, "获取统计数据成功");
    }

    /**
     * @param
     * @return
     * @description 站点排名
     * @date 2020/2/5 5:00 下午
     */
    public RestResponse regionRank(PaymentDataRequest paymentDataRequest) {
        List<RegionPaymentResponse> regionPaymentResponseList = new ArrayList<>();
        //从redis中获取收款数据
        List<PaymentDataModel> paymentDataModelList = getPaymentDataListFromRedis(paymentDataRequest);
        if (paymentDataModelList != null && paymentDataModelList.size() > 0) {
            //声明一个final类型变量来封装数据
            final List<RegionPaymentResponse> finalRegionPaymentResponseList = new ArrayList<>();
            //区域名称对应付款数据
            Map<String, List<PaymentDataModel>> regionNameToPaymentData = paymentDataModelList.stream()
                    .collect(Collectors.groupingBy(a -> {
                        if (StringUtils.isNotBlank(a.getRegionName())) {
                            return a.getRegionName();
                        }
                        return "暂无名称";
                    }));
            regionNameToPaymentData.forEach((key, value) -> {
                RegionPaymentResponse regionPaymentResponse = new RegionPaymentResponse();
                //计划收款总和
                double planMoney = paymentDataModelList.stream().mapToDouble(
                        paymentDataModel -> DataStatisticsUtil.getDoubleValue(paymentDataModel.getPlanMoney())
                ).sum();
                //实际收款总和
                double workMoney = paymentDataModelList.stream().mapToDouble(
                        paymentDataModel -> DataStatisticsUtil.getDoubleValue(paymentDataModel.getWorkMoney())
                ).sum();
                //超期未收总和
                double beyondMoney = planMoney - workMoney;
                regionPaymentResponse.setRegionName(key);
                regionPaymentResponse.setPlanMoney(planMoney);
                regionPaymentResponse.setBeyondMoney(beyondMoney);
                finalRegionPaymentResponseList.add(regionPaymentResponse);
            });
            //通过超期款排名，并取前5的数据
            regionPaymentResponseList = finalRegionPaymentResponseList.stream()
                    .sorted(Comparator.comparing(RegionPaymentResponse::getBeyondMoney)).limit(5)
                    .collect(Collectors.toList());
        }
        return RestResponse.success(regionPaymentResponseList, ApiConstants.RESULT_SUCCESS, "获取统计数据成功");
    }

    /**
     * @param
     * @return
     * @description 超期项目统计
     * @date 2020/2/5 5:02 下午
     */
    public RestResponse dueToProject(PaymentDataRequest paymentDataRequest) {
        List<ProjectPaymentResponse> projectPaymentResponseList = new ArrayList<>();
        //从redis中获取收款数据
        List<PaymentDataModel> paymentDataModelList = getPaymentDataListFromRedis(paymentDataRequest);
        if (paymentDataModelList != null && paymentDataModelList.size() > 0) {
            //声明一个final类型变量来封装数据
            final List<ProjectPaymentResponse> finalProjectPaymentResponseList = new ArrayList<>();
            //将数据转化为项目名->付款数据
            Map<String, List<PaymentDataModel>> projectNameToPaymentData = paymentDataModelList.stream()
                    .collect(Collectors.groupingBy(a -> {
                        if (StringUtils.isNotBlank(a.getProjectName())) {
                            return a.getProjectName();
                        }
                        return "暂无名称";
                    }));
            projectNameToPaymentData.forEach((key, value) -> {
                if (value != null && value.size() > 0) {
                    PaymentDataModel paymentDataModel = value.get(0);
                    ProjectPaymentResponse projectPaymentResponse = new ProjectPaymentResponse();
                    projectPaymentResponse.setProjectName(key);
                    //计划收款总和
                    double planMoney = paymentDataModel.getPlanMoney() != null
                            ? paymentDataModel.getPlanMoney().doubleValue() : 0d;
                    //实际收款总和
                    double workMoney = paymentDataModel.getWorkMoney() != null
                            ? paymentDataModel.getWorkMoney().doubleValue() : 0d;
                    //超期未收总和
                    double beyondMoney = planMoney - workMoney;
                    projectPaymentResponse.setBeyondAmount(beyondMoney);
                    //超期天数 计划收款和实际收款日期差值
                    LocalDate afterDate = LocalDate.now();
                    if (paymentDataModel.getWorkDate() != null) {
                        afterDate = paymentDataModel.getWorkDate();
                    }
                    if (afterDate != null && paymentDataModel.getPlanDate() != null) {
                        projectPaymentResponse.setDueToDays(Long.valueOf(afterDate.until(
                                paymentDataModel.getPlanDate()).getDays()));
                    }
                    //合同金额
                    double contractMoney = paymentDataModel.getContractMoney() != null
                            ? paymentDataModel.getContractMoney().doubleValue() : 0d;
                    projectPaymentResponse.setContractMoney(contractMoney);
                    finalProjectPaymentResponseList.add(projectPaymentResponse);
                }
            });
            //通过超期款倒序
            projectPaymentResponseList = finalProjectPaymentResponseList.stream()
                    .sorted(Comparator.comparing(ProjectPaymentResponse::getBeyondAmount).reversed())
                    .collect(Collectors.toList());
            //判断获取的是前5的数据 还是所有数据
            if (projectPaymentResponseList.size() > 5 && "top5".equals(paymentDataRequest.getProjectScope())) {
                projectPaymentResponseList = projectPaymentResponseList.stream().limit(5).collect(Collectors.toList());
            }
        }
        return RestResponse.success(projectPaymentResponseList, ApiConstants.RESULT_SUCCESS, "获取统计数据成功");
    }
}
