package com.zcxk.charge.web.service.impl;


import com.zcxk.charge.api.dto.query.HomePageReportDto;
import com.zcxk.charge.api.vo.DeviceWaterSupplyVo;
import com.zcxk.charge.api.vo.MonthRevenueVo;
import com.zcxk.charge.core.dao.HomePageReportMapper;
import com.zcxk.charge.core.dao.SceneMapper;
import com.zcxk.charge.core.entity.SceneEntity;
import com.zcxk.charge.web.service.AppPageReportService;
import com.zcxk.charge.web.service.MonitorDataReportService;
import com.zcxk.charge.web.service.RevenueService;
import com.zcxk.core.oauth2.pojo.LoginUser;
import com.zcxk.core.oauth2.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.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;


/**
 * @description
 * @author  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;

    @Override
    public List<DeviceWaterSupplyVo> deviceSellerWaterReportForMonth(Integer companyOrgId, Integer month) {
        LocalDate localDate = LocalDate.now();
        List<DeviceWaterSupplyVo> deviceWaterSupplies = new ArrayList<DeviceWaterSupplyVo>();
        List<MonthRevenueVo> sellerWater = revenueService.selectOverviewRevenue(companyOrgId,month);
        for (int i = 0; i < month; i++) {
            LocalDate newLocalDate = localDate.plusMonths(-i);
            MonthRevenueVo revenue = findRevenue(sellerWater,newLocalDate);
            DeviceWaterSupplyVo deviceWaterSupply = convertDeviceWaterSupplyVo(newLocalDate, i);
            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(DeviceWaterSupplyVo::getOrderNo).reversed());
        return deviceWaterSupplies;
    }

    @Override
    public List<DeviceWaterSupplyVo> deviceWaterReportForMonth(Integer companyOrgId,String sceneType, Integer parmType,Integer month){
        LocalDate localDate = LocalDate.now();
        HomePageReportDto dto = new HomePageReportDto();
        dto.setCompanyOrgId(companyOrgId);
        dto.setSceneType(sceneType);
        dto.setParmType(parmType);
        dto.setMonth(month);
        List<DeviceWaterSupplyVo> deviceWaterSupplies = homePageReportMapper.getDeviceWaterForMonth(dto, UserUtil.getCurrentUser().getUserCondition());
        BigDecimal amountCountMonth = monitorDataReportService.getAmountCount(companyOrgId,null, sceneType, parmType,2 );
        DeviceWaterSupplyVo deviceWaterSupplyMonth = convertDeviceWaterSupplyVo(localDate, 0);
        deviceWaterSupplyMonth.setAmount(amountCountMonth != null ? amountCountMonth.divide(new BigDecimal("10000")):BigDecimal.ZERO);
        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()) {
                DeviceWaterSupplyVo deviceWaterSupply = convertDeviceWaterSupplyVo(newLocalDate, i);
                deviceWaterSupply.setAmount(BigDecimal.ZERO);
                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(DeviceWaterSupplyVo::getOrderNo).reversed());
        return deviceWaterSupplies;
    }

    @Override
    public List<DeviceWaterSupplyVo> deviceWaterReportForDay(Integer companyOrgId, String sceneType, Integer parmType, Integer day) {
        LoginUser loginUser = UserUtil.getCurrentUser();
        LocalDate localDate = LocalDate.now();
        HomePageReportDto dto = new HomePageReportDto();
        dto.setCompanyOrgId(companyOrgId);
        dto.setSceneType(sceneType);
        dto.setParmType(parmType);
        dto.setDay(day);
        List<DeviceWaterSupplyVo> deviceWaterSupplies = homePageReportMapper.getDeviceWaterForDay(dto, loginUser.getUserCondition());
        BigDecimal amountCountMonth = monitorDataReportService.getAmountCount(companyOrgId,null, sceneType, parmType,1);
        DeviceWaterSupplyVo deviceWaterSupplyDay = new DeviceWaterSupplyVo();
        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()) {
                DeviceWaterSupplyVo deviceWaterSupply = convertDeviceWaterSupplyVo(newLocalDate, i);
                deviceWaterSupply.setAmount(BigDecimal.ZERO);
                deviceWaterSupply.setDay(newLocalDate.getDayOfMonth());
                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(DeviceWaterSupplyVo::getOrderNo).reversed());
        return deviceWaterSupplies;
    }

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

        for(DeviceWaterSupplyVo water : supplyWaterList){
            supplyWaterAmount = supplyWaterAmount.add(water.getAmount());
        }

        for(DeviceWaterSupplyVo water : makingWaterList){
            makingWaterAmount = makingWaterAmount.add(water.getAmount());
        }

        for(DeviceWaterSupplyVo 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);
    }

    @Override
    public BigDecimal calculationComparison2(List<DeviceWaterSupplyVo> 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<DeviceWaterSupplyVo> deviceSellerAmountReportForMonth(Integer companyOrgId,Integer month) {
        LocalDate localDate = LocalDate.now();
        List<DeviceWaterSupplyVo> deviceWaterSupplies = new ArrayList<DeviceWaterSupplyVo>();
        List<MonthRevenueVo> sellerWater = revenueService.selectOverviewRevenue(companyOrgId,month);
        for (int i = 0; i < month; i++) {
            LocalDate newLocalDate = localDate.plusMonths(-i);
            MonthRevenueVo revenue = findRevenue(sellerWater,newLocalDate);
            DeviceWaterSupplyVo deviceWaterSupply = convertDeviceWaterSupplyVo(newLocalDate, i);
            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(DeviceWaterSupplyVo::getOrderNo).reversed());
        return deviceWaterSupplies;
    }

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

    private DeviceWaterSupplyVo  convertDeviceWaterSupplyVo(LocalDate newLocalDate, int number){
        DeviceWaterSupplyVo deviceWaterSupply = new DeviceWaterSupplyVo();
        deviceWaterSupply.setOrderNo(number + 1);
        deviceWaterSupply.setYear(newLocalDate.getYear());
        deviceWaterSupply.setMonth(newLocalDate.getMonthValue());
        deviceWaterSupply.setDate(newLocalDate);
        deviceWaterSupply.setDateLabel(newLocalDate.getYear()+"-"+newLocalDate.getMonthValue());
        return deviceWaterSupply;
    }
}