package com.zcxk.service.impl;


import com.zcxk.dao.HomePageReportMapper;

import com.zcxk.dao.SceneMapper;
import com.zcxk.dto.MonthRevenueDto;
import com.zcxk.dto.generalView.DeviceWaterSupply;
import com.zcxk.entity.SceneEntity;
import com.zcxk.model.LoginUser;
import com.zcxk.service.AppPageReportService;
import com.zcxk.service.MonitorDataReportService;
import com.zcxk.service.RevenueService;
import com.zcxk.util.UserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.util.*;


/**
 * @description
 * @auto wangbo
 * @data 2021/3/18 11:00
 */
@Service
public class AppPageReportServiceImpl implements AppPageReportService {

    @Autowired
    private MonitorDataReportService monitorDataReportService;

    @Autowired
    private RevenueService revenueService;

    @Resource
    private HomePageReportMapper homePageReportMapper;

    @Resource
    private SceneMapper sceneMapper;

    /**
     * App 总览 前N个月的售水量
     * @param companyOrgId
     * @return
     */
    @Override
    public List<DeviceWaterSupply> deviceSellerWaterReportForMonth(Integer companyOrgId,Integer month) {
        LocalDate localDate = LocalDate.now();
        List<DeviceWaterSupply> deviceWaterSupplies = new ArrayList<DeviceWaterSupply>();
        List<MonthRevenueDto> sellerWater = revenueService.selectOverviewRevenue(companyOrgId,month);
        for (int i = 0; i < month; i++) {
            LocalDate newLocalDate = localDate.plusMonths(-i);
            MonthRevenueDto revenue = findRevenue(sellerWater,newLocalDate);
            DeviceWaterSupply deviceWaterSupply = new DeviceWaterSupply();
            deviceWaterSupply.setOrderNo(i+1);
            deviceWaterSupply.setYear(newLocalDate.getYear());
            deviceWaterSupply.setMonth(newLocalDate.getMonthValue());
            deviceWaterSupply.setDate(newLocalDate);
            deviceWaterSupply.setDateLabel(newLocalDate.getYear()+"-"+newLocalDate.getMonthValue());
            if(revenue == null){
                deviceWaterSupply.setAmount(BigDecimal.ZERO);
            }
            else{
                deviceWaterSupply.setAmount(new BigDecimal(revenue.getMeterReadingUsage()==null?0:revenue.getMeterReadingUsage()));
            }
            deviceWaterSupplies.add(i, deviceWaterSupply);
        }
        deviceWaterSupplies.sort(Comparator.comparing(DeviceWaterSupply::getOrderNo).reversed());
        return deviceWaterSupplies;
    }

    /**
     * App 总览 前N个月的取水量、制水量
     * @param companyOrgId
     * @param sceneType
     * @param parmType
     * @return
     */
    @Override
    public List<DeviceWaterSupply> deviceWaterReportForMonth(Integer companyOrgId,String sceneType, Integer parmType,Integer month){
        LoginUser loginUser = UserUtil.getCurrentUser();
        String tenantId = loginUser.getTenantId();
        LocalDate localDate = LocalDate.now();
        List<DeviceWaterSupply> deviceWaterSupplies = homePageReportMapper.getDeviceWaterForMonth(companyOrgId,sceneType,parmType ,tenantId,loginUser.getType(),loginUser.getPermissonType(),loginUser.getProgramItemList(),month);
        BigDecimal AmountCountMonth = monitorDataReportService.getAmountCount(companyOrgId,null, sceneType, parmType,2 );
        DeviceWaterSupply deviceWaterSupplyMonth = new DeviceWaterSupply();
        deviceWaterSupplyMonth.setOrderNo(1);
        deviceWaterSupplyMonth.setAmount(AmountCountMonth!=null?AmountCountMonth.divide(new BigDecimal("10000")):BigDecimal.ZERO);
        deviceWaterSupplyMonth.setYear(localDate.getYear());
        deviceWaterSupplyMonth.setMonth(localDate.getMonthValue());
        deviceWaterSupplyMonth.setDate(localDate);
        deviceWaterSupplyMonth.setDateLabel(localDate.getYear()+"-"+localDate.getMonthValue());
        deviceWaterSupplies.add(0, deviceWaterSupplyMonth);

        for (int i = 1; i < month; i++) {
            LocalDate newLocalDate = localDate.plusMonths(-i );
            if (i == deviceWaterSupplies.size()
                    || newLocalDate.getMonthValue() != deviceWaterSupplies.get(i).getMonth().intValue()
                    || newLocalDate.getYear() != deviceWaterSupplies.get(i).getYear().intValue()) {
                DeviceWaterSupply deviceWaterSupply = new DeviceWaterSupply();
                deviceWaterSupply.setOrderNo(i + 1);
                deviceWaterSupply.setAmount(BigDecimal.ZERO);
                deviceWaterSupply.setYear(newLocalDate.getYear());
                deviceWaterSupply.setMonth(newLocalDate.getMonthValue());
                deviceWaterSupply.setDate(newLocalDate);
                deviceWaterSupply.setDateLabel(newLocalDate.getYear()+"-"+newLocalDate.getMonthValue());
                deviceWaterSupplies.add(i, deviceWaterSupply);
            } else {
                deviceWaterSupplies.get(i).setOrderNo(i + 1);
                deviceWaterSupplies.get(i).setDate(newLocalDate);
                deviceWaterSupplies.get(i).setDateLabel(newLocalDate.getYear()+"-"+newLocalDate.getMonthValue());
            }
        }
        deviceWaterSupplies.sort(Comparator.comparing(DeviceWaterSupply::getOrderNo).reversed());

        return deviceWaterSupplies;
    }

    @Override
    public List<DeviceWaterSupply> deviceWaterReportForDay(Integer companyOrgId, String sceneType, Integer parmType, Integer day) {
        LoginUser loginUser = UserUtil.getCurrentUser();
        String tenantId = loginUser.getTenantId();
        LocalDate localDate = LocalDate.now();
        List<DeviceWaterSupply> deviceWaterSupplies = homePageReportMapper.getDeviceWaterForDay(companyOrgId,sceneType,parmType ,tenantId,loginUser.getType(),loginUser.getPermissonType(),loginUser.getProgramItemList(),day);
        BigDecimal AmountCountMonth = monitorDataReportService.getAmountCount(companyOrgId,null, sceneType, parmType,1);
        DeviceWaterSupply deviceWaterSupplyDay = new DeviceWaterSupply();
        deviceWaterSupplyDay.setOrderNo(1);
        deviceWaterSupplyDay.setAmount(AmountCountMonth!=null?AmountCountMonth.divide(new BigDecimal("10000")):BigDecimal.ZERO);
        deviceWaterSupplyDay.setYear(localDate.getYear());
        deviceWaterSupplyDay.setMonth(localDate.getMonthValue());
        deviceWaterSupplyDay.setDay(localDate.getDayOfMonth());
        deviceWaterSupplyDay.setDate(localDate);
        deviceWaterSupplyDay.setDateLabel(localDate.getYear()+"-"+localDate.getMonthValue()+"-"+localDate.getDayOfMonth());
        deviceWaterSupplies.add(0, deviceWaterSupplyDay);
        for (int i = 1; i < day; i++) {
            LocalDate newLocalDate = localDate.plusDays(-i );
            if (i == deviceWaterSupplies.size()
                    || newLocalDate.getDayOfMonth() != deviceWaterSupplies.get(i).getDay().intValue()
                    || newLocalDate.getMonthValue() != deviceWaterSupplies.get(i).getMonth().intValue()
                    || newLocalDate.getYear() != deviceWaterSupplies.get(i).getYear().intValue()) {
                DeviceWaterSupply deviceWaterSupply = new DeviceWaterSupply();
                deviceWaterSupply.setOrderNo(i + 1);
                deviceWaterSupply.setAmount(BigDecimal.ZERO);
                deviceWaterSupply.setYear(newLocalDate.getYear());
                deviceWaterSupply.setMonth(newLocalDate.getMonthValue());
                deviceWaterSupply.setDay(newLocalDate.getDayOfMonth());
                deviceWaterSupply.setDate(newLocalDate);
                deviceWaterSupply.setDateLabel(newLocalDate.getYear()+"-"+newLocalDate.getMonthValue());
                deviceWaterSupplies.add(i, deviceWaterSupply);
            } else {
                deviceWaterSupplies.get(i).setOrderNo(i + 1);
                deviceWaterSupplies.get(i).setDate(newLocalDate);
                deviceWaterSupplies.get(i).setDateLabel(newLocalDate.getYear()+"-"+newLocalDate.getMonthValue());
            }
        }
        deviceWaterSupplies.sort(Comparator.comparing(DeviceWaterSupply::getOrderNo).reversed());

        return deviceWaterSupplies;
    }

    /**
     * @Author wangbo
     * @Description 计算产销差
     * @param makingWaterList 制水量数据
     * @param sellerWaterList 售水量数据
     * @param map
     * @return
     */
    public void CalculationNrw(List<DeviceWaterSupply> supplyWaterList, List<DeviceWaterSupply> makingWaterList,List<DeviceWaterSupply> sellerWaterList,Map<String,Object> map){
        BigDecimal supplyWaterAmount = new BigDecimal(0);
        BigDecimal makingWaterAmount = new BigDecimal(0);
        BigDecimal sellerWaterAmount = new BigDecimal(0);

        for(DeviceWaterSupply water : supplyWaterList){
            supplyWaterAmount = supplyWaterAmount.add(water.getAmount());
        }
        for(DeviceWaterSupply water : makingWaterList){
            makingWaterAmount = makingWaterAmount.add(water.getAmount());
        }
        for(DeviceWaterSupply water : sellerWaterList){
            sellerWaterAmount = sellerWaterAmount.add(water.getAmount());
        }
        BigDecimal nrw = makingWaterAmount.compareTo(BigDecimal.ZERO) == 0  ? BigDecimal.ZERO : makingWaterAmount.subtract(sellerWaterAmount).
                multiply(new BigDecimal(100)).setScale(3,BigDecimal.ROUND_HALF_UP).divide(makingWaterAmount,2, BigDecimal.ROUND_DOWN);
        map.put("totalIntake",supplyWaterAmount);
        map.put("totalMaking",makingWaterAmount);
        map.put("totallSeller",sellerWaterAmount);
        map.put("nrw",nrw);
    }

    /**
     * @Author wangbo
     * @Description 计算环比
     * @param sameWaterList 本月数据
     * @param lastWaterList 上月数据
     * @return
     */
    public BigDecimal CalculationComparison(List<DeviceWaterSupply> sameWaterList, List<DeviceWaterSupply> lastWaterList){
        BigDecimal sameWaterAmount = new BigDecimal(0);
        BigDecimal lastWaterAmount = new BigDecimal(0);
        for(DeviceWaterSupply water : sameWaterList){
            sameWaterAmount = sameWaterAmount.add(water.getAmount());
        }
        for(DeviceWaterSupply water : lastWaterList){
            lastWaterAmount = lastWaterAmount.add(water.getAmount());
        }
        BigDecimal comparison = lastWaterAmount.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : sameWaterAmount.subtract(lastWaterAmount).
                multiply(new BigDecimal(100)).setScale(3,BigDecimal.ROUND_HALF_UP).divide(lastWaterAmount,2, BigDecimal.ROUND_DOWN);
        return comparison;
    }

    public BigDecimal CalculationComparison2(List<DeviceWaterSupply> comparisonList, int type){

        BigDecimal sameWaterAmount = new BigDecimal(0);
        BigDecimal lastWaterAmount = new BigDecimal(0);
        for(int i =0; i<comparisonList.size(); i++){
            if(type == 1){
                if(i==0){
                    lastWaterAmount = lastWaterAmount.add(comparisonList.get(0).getAmount());
                }
                else {
                    sameWaterAmount = sameWaterAmount.add(comparisonList.get(1).getAmount());
                }
            }
            else if(type == 2 || type ==3) {

                if(i>=12){
                    sameWaterAmount = sameWaterAmount.add(comparisonList.get(i).getAmount());
                }
                else{
                    lastWaterAmount = lastWaterAmount.add(comparisonList.get(i).getAmount());
                }
            }
        }


        BigDecimal comparison = lastWaterAmount.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : sameWaterAmount.subtract(lastWaterAmount).
                multiply(new BigDecimal(100)).setScale(3,BigDecimal.ROUND_HALF_UP).divide(lastWaterAmount,2, BigDecimal.ROUND_HALF_UP);
        return comparison;
    }

    @Override
    public List<Map<String,Object>> findSceneAmount(Long companyOrgId,Integer months) {
        SceneEntity sceneEntity = new SceneEntity();
        LoginUser currentUser = UserUtil.getCurrentUser();
        if (currentUser != null) {
            sceneEntity.setTenantId(currentUser.getTenantId());
            sceneEntity.setProgramItems(currentUser.getProgramItemList());
            sceneEntity.setUserType(currentUser.getType());
            //1是公司，2是公司及以下，3部门，4部门及以下，5自定义
            sceneEntity.setPermissonType(currentUser.getPermissonType());
        }
        sceneEntity.setCompanyOrgId(companyOrgId);
        return sceneMapper.findSceneAmount(sceneEntity,months);
    }

    /**
     * App 总览 前N个月的应收实收金额
     * @param companyOrgId
     * @return
     */
    @Override
    public List<DeviceWaterSupply> deviceSellerAmountReportForMonth(Integer companyOrgId,Integer month) {
        LocalDate localDate = LocalDate.now();
        List<DeviceWaterSupply> deviceWaterSupplies = new ArrayList<DeviceWaterSupply>();
        List<MonthRevenueDto> sellerWater = revenueService.selectOverviewRevenue(companyOrgId,month);
        for (int i = 0; i < month; i++) {
            LocalDate newLocalDate = localDate.plusMonths(-i);
            MonthRevenueDto revenue = findRevenue(sellerWater,newLocalDate);
            DeviceWaterSupply deviceWaterSupply = new DeviceWaterSupply();
            deviceWaterSupply.setOrderNo(i+1);
            deviceWaterSupply.setYear(newLocalDate.getYear());
            deviceWaterSupply.setMonth(newLocalDate.getMonthValue());
            deviceWaterSupply.setDate(newLocalDate);
            deviceWaterSupply.setDateLabel(newLocalDate.getYear()+"-"+newLocalDate.getMonthValue());
            if(revenue == null){
                deviceWaterSupply.setReceivableAmount(BigDecimal.ZERO);
                deviceWaterSupply.setReceivedAmount(BigDecimal.ZERO);
                deviceWaterSupply.setGeneralUserAmount(BigDecimal.ZERO);
                deviceWaterSupply.setBigUserAmount(BigDecimal.ZERO);
            }
            else{
                deviceWaterSupply.setReceivableAmount(new BigDecimal(revenue.getReceivableTotalAmount()));
                deviceWaterSupply.setReceivedAmount(new BigDecimal(revenue.getReceivedTotalAmount()));
                deviceWaterSupply.setGeneralUserAmount(new BigDecimal(revenue.getGeneralUserUsage()));
                deviceWaterSupply.setBigUserAmount(new BigDecimal(revenue.getBigUserUsage()));
            }
            deviceWaterSupplies.add(i, deviceWaterSupply);
        }
        deviceWaterSupplies.sort(Comparator.comparing(DeviceWaterSupply::getOrderNo).reversed());
        return deviceWaterSupplies;
    }

    public MonthRevenueDto findRevenue(List<MonthRevenueDto> sellerWater,LocalDate localDate) {
        String dateString = String.format("%s-%s", localDate.getYear(),new DecimalFormat("#00").format(localDate.getMonthValue()));
        for (MonthRevenueDto revenue : sellerWater) {
            if (revenue.getCollectDateString().equals(dateString)) {
                return revenue;
            }
        }
        return null;
    }
}