package com.tofly.qualitycontrol.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.tofly.qualitycontrol.common.QualityControlConstant;
import com.tofly.qualitycontrol.dto.CollectionNumberSummaryAPIBean;
import com.tofly.qualitycontrol.dto.CollectionNumberSummaryBean;
import com.tofly.qualitycontrol.dto.CollectionNumberSummaryClientDTO;
import com.tofly.qualitycontrol.dto.CollectionNumberSummaryDTO;
import com.tofly.qualitycontrol.entity.CollectionNumberDetail;
import com.tofly.qualitycontrol.entity.CollectionNumberSummary;
import com.tofly.qualitycontrol.excel.CollectionNumberSummaryClientExcel;
import com.tofly.qualitycontrol.excel.CollectionNumberSummaryExcel;
import com.tofly.qualitycontrol.exception.QualityControlBusinessException;
import com.tofly.qualitycontrol.mapper.CollectionNumberSummaryMapper;
import com.tofly.qualitycontrol.service.ICollectionNumberDetailService;
import com.tofly.qualitycontrol.service.ICollectionNumberSummaryService;
import com.tofly.qualitycontrol.util.CallAPIUtil;
import com.tofly.qualitycontrol.vo.CollectionNumberClientVO;
import com.tofly.qualitycontrol.vo.CollectionNumberDetailVO;
import com.tofly.qualitycontrol.vo.CollectionNumberSummaryGraphVO;
import com.tofly.qualitycontrol.vo.CollectionNumberSummaryVO;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.alibaba.fastjson.JSON.parseArray;
import static com.alibaba.fastjson.JSON.toJSONString;
import static com.google.common.collect.Lists.newArrayList;
import static com.tofly.qualitycontrol.util.CallAPIUtil.callAPIUtil;
import static com.tofly.qualitycontrol.util.QualityControlUtil.*;
import static java.lang.Double.*;
import static java.net.URLEncoder.encode;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toList;
import static org.apache.commons.collections.CollectionUtils.isEmpty;
import static org.springframework.util.ObjectUtils.nullSafeEquals;

/**
 * @author B
 */
@Service
@RequiredArgsConstructor
public class CollectionNumberSummaryServiceImpl extends ServiceImpl<CollectionNumberSummaryMapper,CollectionNumberSummary> implements ICollectionNumberSummaryService, QualityControlConstant {

	private final ICollectionNumberDetailService collectionNumberDetailService;
	private static final String REGEX = "(?:\\[|null|\\]| +)";
	@Value("${xrtyquality.swagger.ip}")
	private String IP;
	private static final String URL_FEE = "/api/Business/GetReadAndFees";
	private static final String URL_CLIENT = "/api/Business/GetCustomerData";

	@Override
	public IPage<CollectionNumberSummaryVO> getList(String startDate,String endDate,String collectionInfo,String clientNumber,String clientName,Page<CollectionNumberSummary> page) {
		Boolean flag1 = isNotNull(startDate) && isNotNull(endDate);
		Boolean flag2 = isNotNull(collectionInfo);
		Boolean flag3 = isNotNull(clientNumber);
		Boolean flag4 = isNotNull(clientName);

		if (!flag1) {
			return new Page<>(page.getCurrent(),page.getSize(),0);
		}

		QueryWrapper<CollectionNumberSummary> queryWrapper = new QueryWrapper<>();

		//通过客户姓名查询客户编号
		if (flag4) {
			CollectionNumberSummaryAPIBean firstAPIBean = CollectionNumberSummaryAPIBean.builder().ACTION("query").YHXM(clientName).build();
			String yhbh;
			try {
				Map<String,Object> map = callAPIUtil(firstAPIBean,IP,URL_CLIENT);
				Object data = map.get("data");

				String jsonString = toJSONString(data);
				CollectionNumberSummaryBean collectionNumberSummaryBean = parseArray(jsonString,CollectionNumberSummaryBean.class).get(0);
				yhbh = collectionNumberSummaryBean.getYHBH();
			} catch (Exception e) {
				throw new QualityControlBusinessException("第三方数据库异常,请联系管理员");
			}

			queryWrapper = queryWrapper.select("DISTINCT COLLECTION_NUMBER,COLLECTION_NAME")
																		 .like(flag2,"COLLECTION_NUMBER",collectionInfo)
																		 .or()
																		 .like(flag2,"COLLECTION_NAME",collectionInfo)
																		 .like("CLIENT_NUMBER",yhbh)
																		 .orderByAsc("COLLECTION_NUMBER");
		} else {
			queryWrapper = queryWrapper.select("DISTINCT COLLECTION_NUMBER,COLLECTION_NAME")
																		 .like(flag2,"COLLECTION_NUMBER",collectionInfo)
																		 .or()
																		 .like(flag2,"COLLECTION_NAME",collectionInfo)
																		 .like(flag3,"CLIENT_NUMBER",clientNumber)
																		 .orderByAsc("COLLECTION_NUMBER");
		}

		List<CollectionNumberSummaryVO> voList = newArrayList();

		page(page,queryWrapper).getRecords().forEach(l -> {
			CollectionNumberSummaryVO vo = getVO(l,CollectionNumberSummaryVO.class);
			//合计水量初始值
			Double waterVolumeSum = 0.0;
			//合计水费初始值
			BigDecimal waterFeeSum = new BigDecimal("0");
			//合计污水费初始值
			BigDecimal sewageFeeSum = new BigDecimal("0");
			//合计垃圾费初始值
			BigDecimal garbageFeeSum = new BigDecimal("0");

			String collectionNumber = vo.getCollectionNumber();

			List<CollectionNumberDetail> list = collectionNumberDetailService.list(Wrappers.<CollectionNumberDetail>lambdaQuery().eq(CollectionNumberDetail::getCollectionNumber,collectionNumber));

			if (isEmpty(list)) {
				return;
			}

			List<String> clientNumberList = list.stream().map(CollectionNumberDetail::getClientNumber).collect(toList());

			CollectionNumberSummaryAPIBean collectionNumberSummaryAPIBean = CollectionNumberSummaryAPIBean.builder()
																										  .ACTION("query")
																										  .CBYF_START(startDate)
																										  .CBYF_END(endDate)
																										  .YHBH(clientNumberList.toString().replaceAll(REGEX,"")).build();

			try {
				Map<String,Object> map = callAPIUtil(collectionNumberSummaryAPIBean,IP,URL_FEE);
				Object data = map.get("data");

				String jsonString = toJSONString(data);
				List<CollectionNumberSummaryBean> beanList = parseArray(jsonString,CollectionNumberSummaryBean.class);

				for (CollectionNumberSummaryBean bean : beanList) {
					waterVolumeSum += replaceDoubleBadValue(bean.getCBSL());
					sewageFeeSum = sewageFeeSum.add(replaceBigDecimalBadValue(bean.getWSFJE()));
					garbageFeeSum = garbageFeeSum.add(replaceBigDecimalBadValue(bean.getLJFJE()));
					waterFeeSum = waterFeeSum.add(replaceBigDecimalBadValue(bean.getZZSJE()))
											 .add(replaceBigDecimalBadValue(bean.getXFZBJE()))
											 .add(replaceBigDecimalBadValue(bean.getWYJE()))
											 .add(replaceBigDecimalBadValue(bean.getJBSF()))
											 .add(sewageFeeSum)
											 .add(garbageFeeSum);
				}
			} catch (Exception e) {
				throw new QualityControlBusinessException("第三方数据库异常,请联系管理员");
			}

			vo.setWaterVolumeSum(waterVolumeSum)
			  .setSewageFeeSum(sewageFeeSum)
			  .setGarbageFeeSum(garbageFeeSum)
			  .setWaterFeeSum(waterFeeSum);

			voList.add(vo);
		});

		return getIPage(page,voList,list(queryWrapper).size());
	}

	@Override
	@SneakyThrows
	public void export(HttpServletResponse response,CollectionNumberSummaryDTO collectionNumberSummaryDTO) {
		String filename = "汇总统计分析";
		String sheetName = "汇总统计分析表";

		response.setContentType("application/vnd.ms-excel");
		response.setCharacterEncoding("UTF-8");
		response.setHeader("Content-Disposition","attachment;filename=" + encode(filename,"UTF-8") + ".xlsx");
		ServletOutputStream outputStream = response.getOutputStream();

		List<CollectionNumberSummaryVO> dataList = collectionNumberSummaryDTO.getDataList();

		if (CollectionUtils.isEmpty(dataList)) {
			List<List<Object>> list = newArrayList();
			list.add(newArrayList("没有数据!"));

			EasyExcel.write(outputStream)
					 .excelType(ExcelTypeEnum.XLSX)
					 .head((List<List<String>>) null)
					 .sheet(sheetName)
					 .doWrite(list);
			return;
		}

		EasyExcelFactory.write(outputStream,CollectionNumberSummaryExcel.class).sheet(sheetName).doWrite(dataList);
	}

	@Override
	@SneakyThrows
	public void exportData(HttpServletResponse response,String filename,String sheetName,List datas,Class cla){
		response.setContentType("application/vnd.ms-excel");
		response.setCharacterEncoding("UTF-8");
		response.setHeader("Content-Disposition","attachment;filename=" + encode(filename,"UTF-8") + ".xlsx");
		ServletOutputStream outputStream = response.getOutputStream();
		if(CollUtil.isEmpty(datas)){
			List<List<Object>> list = newArrayList();
			list.add(newArrayList("没有数据!"));

			EasyExcel.write(outputStream)
					.excelType(ExcelTypeEnum.XLSX)
					.head((List<List<String>>) null)
					.sheet(sheetName)
					.doWrite(list);
			return;
		}
		EasyExcelFactory.write(outputStream,cla).sheet(sheetName).doWrite(datas);
	}


	@Override
	@SneakyThrows
	public void exportClientDetail(HttpServletResponse response,CollectionNumberSummaryClientDTO collectionNumberSummaryClientDTO) {
		String filename = "客户信息统计分析";
		String sheetName = "客户信息统计分析表";

		response.setContentType("application/vnd.ms-excel");
		response.setCharacterEncoding("UTF-8");
		response.setHeader("Content-Disposition","attachment;filename=" + encode(filename,"UTF-8") + ".xlsx");
		ServletOutputStream outputStream = response.getOutputStream();

		List<CollectionNumberClientVO> dataList = collectionNumberSummaryClientDTO.getDataList();

		if (CollectionUtils.isEmpty(dataList)) {
			List<List<Object>> list = newArrayList();
			list.add(newArrayList("没有数据!"));

			EasyExcel.write(outputStream)
					 .excelType(ExcelTypeEnum.XLSX)
					 .head((List<List<String>>) null)
					 .sheet(sheetName)
					 .doWrite(list);
			return;
		}

		EasyExcelFactory.write(outputStream,CollectionNumberSummaryClientExcel.class).sheet(sheetName).doWrite(dataList);
	}

	@Override
	public IPage<CollectionNumberClientVO> getDetailList(String collectionNumber,String startDate,String endDate,Page<CollectionNumberDetail> page) {
		IPage<CollectionNumberDetailVO> ipage = collectionNumberDetailService.getList(collectionNumber,null,page);

		List<CollectionNumberDetailVO> listRecords = ipage.getRecords();

		if (isEmpty(listRecords)) {
			return new Page<>(page.getCurrent(),page.getSize(),0);
		}

		List<String> clientNumberList = listRecords.stream().map(CollectionNumberDetailVO::getClientNumber).collect(toList());

		List<CollectionNumberClientVO> voList = newArrayList();

		CollectionNumberSummaryAPIBean collectionNumberSummaryAPIBean = CollectionNumberSummaryAPIBean.builder()
																									  .ACTION("query")
																									  .CBYF_START(startDate)
																									  .CBYF_END(endDate)
																									  .YHBH(clientNumberList.toString().replaceAll(REGEX,"")).build();

		try {
			Map<String,Object> map = callAPIUtil(collectionNumberSummaryAPIBean,IP,URL_FEE);
			Object data = map.get("data");

			String jsonString = toJSONString(data);
			List<CollectionNumberSummaryBean> beanList = parseArray(jsonString,CollectionNumberSummaryBean.class);

			beanList.stream().collect(groupingBy(CollectionNumberSummaryBean::getYHBH)).forEach((clientNumber,valueBeanList) -> {
				CollectionNumberClientVO collectionNumberClientVO = CollectionNumberClientVO.builder().build();

				Double waterVolumeSum = 0.0;
				BigDecimal waterFeeSum = new BigDecimal("0");
				BigDecimal sewageFeeSum = new BigDecimal("0");
				BigDecimal garbageFeeSum = new BigDecimal("0");

				for (CollectionNumberSummaryBean valueBean : valueBeanList) {

					waterVolumeSum += replaceDoubleBadValue(valueBean.getCBSL());
					sewageFeeSum = sewageFeeSum.add(replaceBigDecimalBadValue(valueBean.getWSFJE()));
					garbageFeeSum = garbageFeeSum.add(replaceBigDecimalBadValue(valueBean.getLJFJE()));
					waterFeeSum = waterFeeSum.add(replaceBigDecimalBadValue(valueBean.getZZSJE()))
											 .add(replaceBigDecimalBadValue(valueBean.getXFZBJE()))
											 .add(replaceBigDecimalBadValue(valueBean.getWYJE()))
											 .add(replaceBigDecimalBadValue(valueBean.getJBSF()))
											 .add(sewageFeeSum)
											 .add(garbageFeeSum);

					collectionNumberClientVO.setClientName(valueBean.getYHXM())
											.setClientAddress(valueBean.getYHDZ())
											.setClientPhone(valueBean.getLXDH());
				}
				collectionNumberClientVO.setClientNumber(clientNumber)
										.setWaterVolumeSum(waterVolumeSum)
										.setSewageFeeSum(sewageFeeSum)
										.setGarbageFeeSum(garbageFeeSum)
										.setWaterFeeSum(waterFeeSum);

				voList.add(collectionNumberClientVO);
			});
		} catch (Exception e) {
			throw new QualityControlBusinessException("第三方数据库异常,请联系管理员");
		}

		//存在有客户没有数据的情况
		int i = listRecords.size() - voList.size();

		return getIPage(page,voList,ipage.getTotal() - i);
	}

	@Override
	public List<CollectionNumberSummaryGraphVO> getCollectionMonthGraph(String collectionNumber,String startDate,String endDate) {
		Boolean flag = isNull(startDate) && isNull(endDate);
		if (flag) {
			throw new QualityControlBusinessException("日期不能为空");
		}

		List<CollectionNumberSummaryGraphVO> voList = Lists.newArrayList();

		List<CollectionNumberDetail> list = collectionNumberDetailService.list(Wrappers.<CollectionNumberDetail>lambdaQuery().eq(CollectionNumberDetail::getCollectionNumber,collectionNumber));

		if (CollectionUtils.isEmpty(list)) {
			return null;
		}

		List<String> clientNumberList = list.stream().map(CollectionNumberDetail::getClientNumber).collect(toList());

		CollectionNumberSummaryAPIBean collectionNumberSummaryAPIBean = CollectionNumberSummaryAPIBean.builder()
																									  .ACTION("query")
																									  .CBYF_START(startDate)
																									  .CBYF_END(endDate)
																									  .YHBH(clientNumberList.toString().replaceAll(REGEX,"")).build();

		try {
			Map<String,Object> map = CallAPIUtil.callAPIUtil(collectionNumberSummaryAPIBean,IP,URL_FEE);
			Object data = map.get("data");

			String jsonString = toJSONString(data);
			List<CollectionNumberSummaryBean> beanList = parseArray(jsonString,CollectionNumberSummaryBean.class);

			beanList.stream().collect(Collectors.groupingBy(CollectionNumberSummaryBean::getCBYF,LinkedHashMap::new,toList())).forEach((date,valueBeanList) -> {
				Double waterVolumeSum = 0.0;

				for (CollectionNumberSummaryBean valueBean : valueBeanList) {
					waterVolumeSum += replaceDoubleBadValue(valueBean.getCBSL());
				}

				CollectionNumberSummaryGraphVO collectionNumberSummaryGraphVO = CollectionNumberSummaryGraphVO.builder()
																											  .date(date)
																											  .waterVolumeSum(waterVolumeSum).build();
				voList.add(collectionNumberSummaryGraphVO);
			});
		} catch (Exception e) {
			throw new QualityControlBusinessException("第三方数据库异常,请联系管理员");
		}

		return voList;
	}

	@Override
	public List<CollectionNumberSummaryGraphVO> getClientMonthGraph(String clientNumber,String startDate,String endDate) {
		Boolean flag = isNull(startDate) && isNull(endDate);
		if (flag) {
			throw new QualityControlBusinessException("日期不能为空");
		}

		List<CollectionNumberSummaryGraphVO> voList = Lists.newArrayList();

		CollectionNumberSummaryAPIBean collectionNumberSummaryAPIBean = CollectionNumberSummaryAPIBean.builder()
																									  .ACTION("query")
																									  .CBYF_START(startDate)
																									  .CBYF_END(endDate)
																									  .YHBH(clientNumber).build();

		try {
			Map<String,Object> map = CallAPIUtil.callAPIUtil(collectionNumberSummaryAPIBean,IP,URL_FEE);
			Object data = map.get("data");

			String jsonString = toJSONString(data);
			List<CollectionNumberSummaryBean> beanList = parseArray(jsonString,CollectionNumberSummaryBean.class);

			beanList.stream().sorted(Comparator.comparing(CollectionNumberSummaryBean::getCBYF)).collect(toList()).forEach(bean -> {

				Double waterVolumeSum = replaceDoubleBadValue(bean.getCBSL());
				CollectionNumberSummaryGraphVO collectionNumberSummaryGraphVO = CollectionNumberSummaryGraphVO.builder()
																											  .date(bean.getCBYF())
																											  .waterVolumeSum(waterVolumeSum).build();
				voList.add(collectionNumberSummaryGraphVO);
			});
		} catch (Exception e) {
			throw new QualityControlBusinessException("第三方数据库异常,请联系管理员");
		}

		return voList;
	}

	@Override
	public List<CollectionNumberSummaryGraphVO> getClientHistoryGraph(String clientNumber) {
		Calendar calendar = Calendar.getInstance();

		calendar.add(Calendar.MONTH, -3);
		String startDate = new SimpleDateFormat("yyyyMM").format(calendar.getTime());

		calendar.add(Calendar.MONTH, 2);
		String endDate = new SimpleDateFormat("yyyyMM").format(calendar.getTime());

		return getClientMonthGraph(clientNumber,startDate,endDate);
	}

	private Double replaceDoubleBadValue(Double value) {
		return nullSafeEquals(value,null) || nullSafeEquals(value,NaN) || nullSafeEquals(value,POSITIVE_INFINITY) || nullSafeEquals(value,NEGATIVE_INFINITY) ? 0.0 : value;
	}

	private BigDecimal replaceBigDecimalBadValue(BigDecimal value) {
		return nullSafeEquals(value,null) ? new BigDecimal("0") : value;
	}

}
