/**
 *
 */
package org.springblade.finance.controller;

import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springblade.audit.entity.BladeReportTask;
import org.springblade.audit.service.IBladeReportTaskService;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.utils.SecureUtil;
import org.springblade.core.tool.api.R;
import org.springblade.finance.dto.DateRangeAccountExcel;
import org.springblade.finance.dto.DateRangeAccountPdfToExcel;
import org.springblade.finance.dto.DateRangeUsersExcel;
import org.springblade.finance.dto.DownloadPdfDTO;
import org.springblade.finance.entity.*;
import org.springblade.finance.service.*;
import org.springblade.system.client.UserClient;
import org.springblade.system.client.model.UserModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.security.SecurityProperties.User;
import org.springframework.web.bind.annotation.*;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

/**
 * @author wookvn
 *
 */
@RestController
@RequestMapping("finance/dateRangeAccount")
@Api(value = "结算表", tags = "结算表接口")
@Slf4j
public class DateRangeAccountController extends BladeController{

	@Autowired
	private DateRangeAccountService dateRangeAccountService;

	@Autowired
	private IIntOndaterangeAccountService intOndaterangeAccountService;

	@Autowired
	private DateRangeUsersService dateRangeUsersService;

	@Autowired
	private ChannelSpidService channelSpidService;

	@Autowired
	private PdfExportService pdfExportService;

	@Autowired
	private PdfExportWXService pdfExportWXService;

	@Autowired
	private FinanceBillAuditService financeBillAuditService;

	@Autowired
	private IIntOndaterangeAccountFileService intOndaterangeAccountFileService;

	@Autowired
	private IBladeReportTaskService bladeReportTaskService;

	@Autowired
	private DealUserAccountsService dealUserAccountsService;

	@Autowired
	private IntCwDetailViewService intCwDetailViewService;

	@Autowired
	private UserClient userService;

	@Autowired
	private IIntChannelsService intChannelsService;

	public final static int batchSize = 3000;

	/**
	 * @param query
	 * @return
	 */
	@GetMapping("/list")
	@ApiOperation(value = "分页查询结算表数据")
	@ApiImplicitParams({
		@ApiImplicitParam(name = "dealUserIds", value = "结算用户ID，逗号隔开。全部渠道传空或者不传递", required = false),
		@ApiImplicitParam(name = "spid", value = "产品ID", dataType = "string", required = false),
		@ApiImplicitParam(name = "startTime", value = "开始日期(格式：yyyy-MM)", dataType = "string", required = false),
		@ApiImplicitParam(name = "endTime", value = "结束日期(格式：yyyy-MM)", dataType = "string", required = false)
	})
	public R<IPage<DateRangeAccount>> list(String[] dealUserIds, String spid, String startTime,String endTime, Query query){
		if(query.getSize() == null){
			query.setSize(5);
		}
		LambdaQueryWrapper<DateRangeAccount> queryWrapper = Wrappers.<DateRangeAccount>lambdaQuery();
		if(dealUserIds != null && dealUserIds.length > 0) {
			List<String> strings = Arrays.asList(dealUserIds);
			List<String> collect = null;
			if(strings != null && strings.size() > 0){
				QueryWrapper<DealUserAccounts> dealQueryWrapper = new QueryWrapper<DealUserAccounts>();
				dealQueryWrapper.select("DEAL_ACCOUNT_ID").isNotNull("DEAL_ACCOUNT_ID");
				dealQueryWrapper.in("DEAL_USERID",strings);
				List<DealUserAccounts> dealList = dealUserAccountsService.list(dealQueryWrapper);
				collect = dealList.stream().map(DealUserAccounts::getDealAccountId).collect(Collectors.toList());
			}
			queryWrapper.in(DateRangeAccount::getDealAccountId, collect);
		}
		if(StringUtils.isNotEmpty(spid)) {
			queryWrapper.eq(DateRangeAccount::getSpid, spid);
		}
		if(StringUtils.isNotEmpty(startTime) && parseDateString(startTime) != 0) {
			int startDate = Integer.valueOf(startTime.replaceAll("\\-", ""));
			queryWrapper.ge(DateRangeAccount::getTheMonth, startDate);
		}
		if(StringUtils.isNotEmpty(endTime) && parseDateString(endTime) != 0) {
			int endDate = Integer.valueOf(endTime.replaceAll("\\-", ""));
			queryWrapper.le(DateRangeAccount::getTheMonth, endDate);
		}
		Integer thisMonth = Integer.valueOf(DateTimeFormatter.ofPattern("yyyyMM").format(LocalDate.now()));
		queryWrapper.lt(DateRangeAccount::getTheMonth, thisMonth);
		IPage<DateRangeAccount> pageResult = dateRangeAccountService.page(Condition.getPage(query), queryWrapper.orderByDesc(DateRangeAccount::getTheMonth, DateRangeAccount::getChannelId));
		if(pageResult != null && pageResult.getRecords() != null) {
			pageResult.getRecords().stream().forEach(f -> {
				List<IntOndaterangeAccountFile> list = intOndaterangeAccountFileService.list(new LambdaQueryWrapper<IntOndaterangeAccountFile>()
					.eq(IntOndaterangeAccountFile::getSid, f.getSid())
				);
				f.setFileList(list);
				BigDecimal pct = new BigDecimal(f.getMatchPct()).multiply(new BigDecimal(100)).setScale(BigDecimal.ROUND_HALF_UP,2);
				f.setMatchPct(pct.doubleValue());
				String pctStr = pct.toString().substring(0, pct.toString().indexOf("."));
				f.setMatchPctStr(pctStr+"%");
			});
		}
		return R.data(pageResult);
	}


	private static List<String> getMonthBetween(String startTime, String endTime) {
		ArrayList<String> result = new ArrayList<String>();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");// 格式化为年月
		try {
			Calendar min = Calendar.getInstance();
			Calendar max = Calendar.getInstance();

			min.setTime(sdf.parse(startTime));
			min.set(min.get(Calendar.YEAR), min.get(Calendar.MONTH), 1);

			max.setTime(sdf.parse(endTime));
			max.set(max.get(Calendar.YEAR), max.get(Calendar.MONTH), 2);

			Calendar curr = min;
			while (curr.before(max)) {
				result.add(sdf.format(curr.getTime()));
				curr.add(Calendar.MONTH, 1);
			}

			Collections.sort(result, new Comparator<Object>() {
				@Override
				public int compare(Object o1, Object o2) {
					String str1 = (String) o1;
					String str2 = (String) o2;
					SimpleDateFormat format = new SimpleDateFormat("yyyyMM");
					Date date1 = null;
					Date date2 = null;
					try {
						date1 = format.parse(str1);
						date2 = format.parse(str2);
					} catch (ParseException e) {
						e.printStackTrace();
					}

					if (date2.compareTo(date1) > 0) {
						return -1;
					}
					return 1;
				}
			});
		}catch (ParseException e) {
			e.printStackTrace();
		}
		return result;
	}


	@PostMapping("/editFlagRender")
	@ApiOperation(value = "编辑报账状态")
	@ApiImplicitParams({
		@ApiImplicitParam(name = "sid", value = "sid唯一ID", required = true),
		@ApiImplicitParam(name = "isFlag", value = "报账状态 0：未报账；1：已报账；", dataType = "Integer", required = true),
		@ApiImplicitParam(name = "flagType", value = "报账类型 1 第一次报账（T+1预结） 2 第二次报账 （T+4/T+5清算）", dataType = "Integer", required = true)
	})
	public R edit(Long sid,Integer isFlag,Integer flagType){
		Long userId = SecureUtil.getUserId();
		if(sid == null || (isFlag != 0 && isFlag!= 1)){
			return R.fail("参数异常");
		}
		//第一次报账 flagType 预结是第一次 0 清算第二次 1
		if(flagType == 0){
			return R.data(dateRangeAccountService.editFlagRenderFirst(sid,isFlag,userId));
		}
		//清算第二次
		if(flagType == 1){
			return R.data(dateRangeAccountService.editFlagRenderSecond(sid,isFlag,userId));
		}
		return R.fail("编辑报账状态异常");
	}


	@PostMapping("/percheck")
	@ApiOperation(value = "预审")
	public R reject(@RequestParam Long sid,@RequestParam Integer percheckFlag){
		Long userId = SecureUtil.getUserId();
		//todo 测试环境小强为预审人、正式换为张凯
		if(userId != 1392663744517726210L){
			return R.fail("您没有预审权限");
		}
		if(sid == null || percheckFlag == null){
			return R.fail("参数异常");
		}
		if(percheckFlag != 1 && percheckFlag != 2){
			return R.fail("预审状态错误");
		}
		IntOndaterangeAccount entity = intOndaterangeAccountService.getOne(new LambdaQueryWrapper<IntOndaterangeAccount>()
			.eq(IntOndaterangeAccount::getSid, sid)
			.eq(IntOndaterangeAccount::getPercheckFlag,0)
		);
		if(entity == null){
			return R.fail("预审数据已审核/不存在");
		}
		UserModel byId = userService.getById(userId);
		entity.setPercheckFlag(percheckFlag);
		entity.setPercheckTime(new Date());
		entity.setPerchecker(byId.getRealName());
		return R.status(intOndaterangeAccountService.update(entity,new LambdaUpdateWrapper<IntOndaterangeAccount>().eq(IntOndaterangeAccount::getSid,sid)));
	}


	/**
	 * 社会渠道结算，渠道结算明细列表
	 * @param dealUserIds
	 * @param spid
	 * @param startTime
	 * @param endTime
	 * @param isFlag
	 * @param theMonth
	 * @param query
	 * @return
	 */
	@GetMapping("/redayList")
	@ApiOperation(value = "预结/清算分页查询")
	@ApiImplicitParams({
		@ApiImplicitParam(name = "dealUserIds", value = "结算用户ID，逗号隔开。全部渠道传空或者不传递", required = false),
		@ApiImplicitParam(name = "spid", value = "产品ID", dataType = "string", required = false),
		@ApiImplicitParam(name = "startTime", value = "开始月份(格式：yyyyMM)", dataType = "string", required = false),
		@ApiImplicitParam(name = "endTime", value = "结束月份(格式：yyyyMM)", dataType = "string", required = false),
		@ApiImplicitParam(name = "isFlag", value = "是否报账标记：0：未报账；1：已报账", dataType = "Integer", required = false),
		@ApiImplicitParam(name = "dealType", value = "结算类型：0：预结；1：清算；", dataType = "Integer", required = false),
		@ApiImplicitParam(name = "theMonth", value = "账期(格式：yyyyMM)", dataType = "string", required = false)
	})
	public R<IPage<IntCwDetailView>> redayList(String[] dealUserIds, String spid, String startTime, String endTime, Integer isFlag,Integer dealType, String theMonth, Query query){
		//List<String> monthBetween = getMonthBetween(startTime, endTime);
		//LambdaQueryWrapper<DateRangeAccount> queryWrapper = Wrappers.<DateRangeAccount>lambdaQuery();
		LambdaQueryWrapper<IntCwDetailView> queryWrapper = Wrappers.<IntCwDetailView>lambdaQuery();
		if(dealUserIds != null && dealUserIds.length > 0) {
			List<String> strings = Arrays.asList(dealUserIds);
			List<String> collect = null;
			if(strings != null && strings.size() > 0){
				QueryWrapper<DealUserAccounts> dealQueryWrapper = new QueryWrapper<DealUserAccounts>();
				dealQueryWrapper.select("DEAL_ACCOUNT_ID").isNotNull("DEAL_ACCOUNT_ID");
				dealQueryWrapper.in("DEAL_USERID",strings);
				List<DealUserAccounts> dealList = dealUserAccountsService.list(dealQueryWrapper);
				collect = dealList.stream().map(DealUserAccounts::getDealAccountId).collect(Collectors.toList());
			}
			queryWrapper.in(IntCwDetailView::getDealAccountId, collect);
		}
		if(StringUtils.isNotEmpty(spid)) {
			queryWrapper.eq(IntCwDetailView::getSpid, spid);
		}
		if(StringUtils.isNotEmpty(theMonth)){
			queryWrapper.eq(IntCwDetailView::getThemonth, theMonth);
		}
		if(isFlag != null){
			queryWrapper.eq(IntCwDetailView::getFlagRender, isFlag);
		}
		if(dealType != null){
			queryWrapper.eq(IntCwDetailView::getDealTypeid, dealType);
		}
		if(StringUtils.isNotEmpty(startTime)) {
			int startDate = Integer.valueOf(startTime);
			queryWrapper.ge(IntCwDetailView::getThemonth, startDate);
		}
		if(StringUtils.isNotEmpty(endTime)) {
			int endDate = Integer.valueOf(endTime);
			queryWrapper.le(IntCwDetailView::getThemonth, endDate);
		}
		if(query.getSize() == null){
			query.setSize(5);
		}
		IPage<IntCwDetailView> page = intCwDetailViewService.page(Condition.getPage(query), queryWrapper.orderByDesc(IntCwDetailView::getThemonth));

		/*LocalDate startLocalDate = LocalDate.parse(startTime + "01", DateTimeFormatter.BASIC_ISO_DATE);
		LocalDate endLocalDate = LocalDate.parse(endTime+"01", DateTimeFormatter.BASIC_ISO_DATE);
		LocalDate start = startLocalDate.plusMonths(-5);
		LocalDate between = startLocalDate.plusMonths(-4);
		LocalDate end = endLocalDate.plusMonths(-1);

		Integer startInt = Integer.valueOf(DateTimeFormatter.ofPattern("yyyyMM").format(start));
		Integer betweenInt = Integer.valueOf(DateTimeFormatter.ofPattern("yyyyMM").format(between));
		Integer endInt = Integer.valueOf(DateTimeFormatter.ofPattern("yyyyMM").format(end));

		if(startTime.equals(endTime)){
			queryWrapper.and(f -> {
				f.eq(DateRangeAccount::getTheMonth,endInt)
					.or()
					.eq(DateRangeAccount::getTheMonth, startInt)
					.or()
					.eq(DateRangeAccount::getTheMonth, betweenInt);
			});
		}else {
			queryWrapper.and(f -> {
				f.le(DateRangeAccount::getTheMonth,endInt).ge(DateRangeAccount::getTheMonth, startInt);
			});
		}
		List<DateRangeAccount> resultList = dateRangeAccountService.list(queryWrapper.orderByDesc(DateRangeAccount::getTheMonth, DateRangeAccount::getChannelId));
		if(resultList != null && resultList != null) {
			resultList.forEach(f -> {
				for (String themonth : monthBetween) {
					LocalDate t0theMonth = LocalDate.parse(themonth + "01", DateTimeFormatter.BASIC_ISO_DATE);
					LocalDate t1theMonth = t0theMonth.plusMonths(-1);
					LocalDate t4theMonth = t0theMonth.plusMonths(-4);
					LocalDate t5theMonth = t0theMonth.plusMonths(-5);
					Integer t1Int = Integer.valueOf(DateTimeFormatter.ofPattern("yyyyMM").format(t1theMonth));
					Integer t4Int = Integer.valueOf(DateTimeFormatter.ofPattern("yyyyMM").format(t4theMonth));
					Integer t5Int = Integer.valueOf(DateTimeFormatter.ofPattern("yyyyMM").format(t5theMonth));

					if(f.getChannelName().equals("微信支付") && StringUtils.isNotBlank(f.getChannelName()) && (f.getTheMonth().intValue() == t1Int || f.getTheMonth().intValue() ==  t4Int)){
						f.setReadyTypeStr(f.getTheMonth().intValue() == (Integer.valueOf(DateTimeFormatter.ofPattern("yyyyMM").format(LocalDate.parse(themonth + "01", DateTimeFormatter.BASIC_ISO_DATE).plusMonths(-1)))) ? "T+1预结" : "T+4清算");
					}
					if(StringUtils.isNotBlank(f.getChannelName()) && (f.getTheMonth().intValue() == t1Int || f.getTheMonth().intValue() ==  t5Int)){
						f.setReadyTypeStr(f.getTheMonth().intValue() == (Integer.valueOf(DateTimeFormatter.ofPattern("yyyyMM").format(LocalDate.parse(themonth + "01", DateTimeFormatter.BASIC_ISO_DATE).plusMonths(-1)))) ? "T+1预结" : "T+5清算");
					}
				}
			});
		}

		List<DateRangeAccount> collect = resultList.stream().filter(item -> StringUtils.isNotBlank(item.getReadyTypeStr())).collect(Collectors.toList());
		*/
		return R.data(page);
	}


	/**
	 * 下载结算表PDF数据 (互联网1 ， 社会渠道结算)
	 * @param reqType  1 社会渠道结算 2 互联网1
	 * @param downloadType
	 * @param spid
	 * @param dealAccountId
	 * @param theMonth
	 * @param response
	 * @throws Exception
	 */
	@GetMapping("/downloadPdf")
	@ApiOperation(value = "下载结算表PDF数据")
	public void downloadPdf(@RequestParam Integer reqType,@RequestParam String downloadType,@RequestParam String spid, @RequestParam String dealAccountId ,@RequestParam Integer theMonth, HttpServletResponse response) throws Exception {
		LambdaQueryWrapper<DateRangeAccount> queryWrapper = Wrappers.lambdaQuery(DateRangeAccount.class).eq(DateRangeAccount::getDealAccountId, dealAccountId)
						.eq(DateRangeAccount::getSpid, spid).eq(DateRangeAccount::getTheMonth, theMonth);
		DateRangeAccount dateRangeAccount = dateRangeAccountService.getOne(queryWrapper);
		if(dateRangeAccount != null) {
			/*ChannelSpid channelSpid = channelSpidService.getOne(Wrappers.lambdaQuery(ChannelSpid.class).eq(ChannelSpid::getSpid, dateRangeAccount.getSpid()).eq(ChannelSpid::getDealAccountId, dealAccountId));
			if(channelSpid != null) {
				dateRangeAccount.setPartnerIncome(channelSpid.getPartnerIncome());
			}*/
			// Http 1.0 header
	        response.setDateHeader("Expires", 0);
	        response.addHeader("Pragma", "no-cache");
	        // Http 1.1 header
	        response.setHeader("Cache-Control", "no-cache");
	        String encodedfileName = new String((("one".equalsIgnoreCase(downloadType) ? "第一次" : "第二次") + "结算确认单").getBytes("GBK"), "ISO8859-1");
	        response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedfileName + ".pdf\"");
			response.setContentType("application/vnd.ms-pdf");

			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			if(reqType == null){
				reqType = 2;
			}
			//社会渠道结算
			if(reqType == 1){
				if(dateRangeAccount.getChannelName().equals("微信支付")){
					if("one".equals(downloadType)) {
						pdfExportWXService.createOnePdf(dateRangeAccount, baos);
					}else {
						pdfExportWXService.createTwoPdf(dateRangeAccount, baos);
					}
				}else if("one".equals(downloadType)) {
					pdfExportService.createOnePdf(dateRangeAccount, baos);
				}else {
					pdfExportService.createTwoPdf(dateRangeAccount, baos);
				}
			}
			//互联网1 去掉总扣罚金额字段
			if(reqType == 2){
				if(dateRangeAccount.getChannelName().equals("微信支付")){
					if("one".equals(downloadType)) {
						pdfExportWXService.createOnePdf(dateRangeAccount, baos);
					}else {
						pdfExportWXService.createTwoPdf(dateRangeAccount, baos);
					}
				}else if("one".equals(downloadType)) {
					pdfExportService.createH1OnePdf(dateRangeAccount, baos);
				}else {
					pdfExportService.createH1TwoPdf(dateRangeAccount, baos);
				}
			}
			response.getOutputStream().write(baos.toByteArray());
			response.getOutputStream().flush();
		}
	}


	@GetMapping("/downloadRedayExcel")
	@ApiOperation(value = "下载预结/清算Excel")
	@ApiImplicitParams({
		@ApiImplicitParam(name = "sids", value = "渠道ID，逗号隔开。全部渠道传空或者不传递", required = false),
		@ApiImplicitParam(name = "dealUserIds", value = "渠道ID，逗号隔开。全部渠道传空或者不传递", required = false),
		@ApiImplicitParam(name = "spid", value = "产品ID", dataType = "string", required = false),
		@ApiImplicitParam(name = "startTime", value = "开始月份(格式：yyyyMM)", dataType = "string", required = false),
		@ApiImplicitParam(name = "endTime", value = "结束月份(格式：yyyyMM)", dataType = "string", required = false),
		@ApiImplicitParam(name = "isFlag", value = "是否报账标记：0：未报账；1：已报账", dataType = "Integer", required = false),
		@ApiImplicitParam(name = "dealType", value = "结算类型：0：预结；1：清算；", dataType = "Integer", required = false),
		@ApiImplicitParam(name = "theMonth", value = "账期(格式：yyyyMM)", dataType = "string", required = false)
	})
	public void downloadRedayExcel(String[] sids, String[] dealUserIds, String spid, String startTime,String endTime,Integer isFlag,Integer dealType,String theMonth, HttpServletResponse response) throws Exception{
		LambdaQueryWrapper<IntCwDetailView> queryWrapper = Wrappers.<IntCwDetailView>lambdaQuery();
		if(sids != null && sids.length > 0){
			queryWrapper.in(IntCwDetailView::getSid, Arrays.asList(sids));
		}else {
			if(dealUserIds != null && dealUserIds.length > 0) {
				List<String> strings = Arrays.asList(dealUserIds);
				List<String> collect = null;
				if(strings != null && strings.size() > 0){
					QueryWrapper<DealUserAccounts> dealQueryWrapper = new QueryWrapper<DealUserAccounts>();
					dealQueryWrapper.select("DEAL_ACCOUNT_ID").isNotNull("DEAL_ACCOUNT_ID");
					dealQueryWrapper.in("DEAL_USERID",strings);
					List<DealUserAccounts> dealList = dealUserAccountsService.list(dealQueryWrapper);
					collect = dealList.stream().map(DealUserAccounts::getDealAccountId).collect(Collectors.toList());
				}
				queryWrapper.in(IntCwDetailView::getDealAccountId, collect);
			}

			if(StringUtils.isNotEmpty(spid)) {
				queryWrapper.eq(IntCwDetailView::getSpid, spid);
			}
			if(StringUtils.isNotEmpty(theMonth)){
				queryWrapper.eq(IntCwDetailView::getThemonth, theMonth);
			}
			if(isFlag != null){
				queryWrapper.eq(IntCwDetailView::getFlagRender, isFlag);
			}
			if(dealType != null){
				queryWrapper.eq(IntCwDetailView::getDealTypeid, dealType);
			}
			if(StringUtils.isNotEmpty(startTime)) {
				int startDate = Integer.valueOf(startTime);
				queryWrapper.ge(IntCwDetailView::getThemonth, startDate);
			}
			if(StringUtils.isNotEmpty(endTime)) {
				int endDate = Integer.valueOf(endTime);
				queryWrapper.le(IntCwDetailView::getThemonth, endDate);
			}
		}
		List<IntCwDetailView> list = intCwDetailViewService.list(queryWrapper.orderByDesc(IntCwDetailView::getThemonth));
		List<DateRangeAccountPdfToExcel> accountList = new ArrayList<DateRangeAccountPdfToExcel>();

		if(list != null && !list.isEmpty()) {
			for (IntCwDetailView intCwDetailView : list) {
				DateRangeAccountPdfToExcel excel = new DateRangeAccountPdfToExcel();
				BeanUtil.copyProperties(intCwDetailView,excel);
				accountList.add(excel);
			}
		}

		//response.setContentType("application/vnd.ms-excel");
		response.setCharacterEncoding("utf-8");
		// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
		String fileName = URLEncoder.encode("渠道结算明细表", "UTF-8");
		response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
		ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
			.excelType(ExcelTypeEnum.XLSX).build();  //.password("123456")
		WriteSheet writeSheet = EasyExcel.writerSheet("数据").head(DateRangeAccountPdfToExcel.class).build();
		excelWriter.write(accountList, writeSheet);
		excelWriter.finish();
	}


	/**
	 * @return
	 * @throws Exception
	 */
	@PostMapping("/downloadRedayPdfBySid")
	@ApiOperation(value = "多选下载预结/清算PDF")
	public void downloadRedayPdfBySid(@RequestBody List<DownloadPdfDTO> dto, HttpServletResponse response) throws Exception{
		List<IntCwDetailView> list = new ArrayList<IntCwDetailView>();
		if(dto != null && dto.size() > 0){
			for (DownloadPdfDTO downloadPdfDTO : dto) {
				LambdaQueryWrapper<IntCwDetailView> queryWrapper = Wrappers.<IntCwDetailView>lambdaQuery();
				queryWrapper.eq(IntCwDetailView::getSid,downloadPdfDTO.getSid());
				queryWrapper.eq(IntCwDetailView::getDealTypeid,downloadPdfDTO.getDealType());
				IntCwDetailView one = intCwDetailViewService.getOne(queryWrapper);
				if(one != null){
					list.add(one);
				}
			}
		}
		// Http 1.0 header
		response.setDateHeader("Expires", 0);
		response.addHeader("Pragma", "no-cache");
		// Http 1.1 header
		response.setHeader("Cache-Control", "no-cache");
		String encodedfileName = new String(("结算明细单").getBytes("GBK"), "ISO8859-1");
		response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedfileName + ".pdf\"");
		response.setContentType("application/vnd.ms-pdf");

		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		pdfExportService.createReadyPdf(list, baos);
		response.getOutputStream().write(baos.toByteArray());
		response.getOutputStream().flush();
	}

	/**
	 *
	 * @return
	 * @throws Exception
	 */
	@GetMapping("/downloadRedayPdf")
	@ApiOperation(value = "下载预结/清算PDF")
	@ApiImplicitParams({
		@ApiImplicitParam(name = "sids", value = "渠道ID，逗号隔开。全部渠道传空或者不传递", required = false),
		@ApiImplicitParam(name = "dealUserIds", value = "渠道ID，逗号隔开。全部渠道传空或者不传递", required = false),
		@ApiImplicitParam(name = "spid", value = "产品ID", dataType = "string", required = false),
		@ApiImplicitParam(name = "startTime", value = "开始月份(格式：yyyyMM)", dataType = "string", required = false),
		@ApiImplicitParam(name = "endTime", value = "结束月份(格式：yyyyMM)", dataType = "string", required = false),
		@ApiImplicitParam(name = "isFlag", value = "是否报账标记：0：未报账；1：已报账", dataType = "Integer", required = false),
		@ApiImplicitParam(name = "dealType", value = "结算类型：0：预结；1：清算；", dataType = "Integer", required = false),
		@ApiImplicitParam(name = "theMonth", value = "账期(格式：yyyyMM)", dataType = "string", required = false)
	})
	public void downloadRedayPdf(String[] sids, String[] dealUserIds, String spid, String startTime,String endTime, Integer isFlag,Integer dealType,String theMonth, HttpServletResponse response) throws Exception{
		LambdaQueryWrapper<IntCwDetailView> queryWrapper = Wrappers.<IntCwDetailView>lambdaQuery();
		if(sids != null && sids.length > 0){
			queryWrapper.in(IntCwDetailView::getSid, Arrays.asList(sids));
		}else {
			if(dealUserIds != null && dealUserIds.length > 0) {
				List<String> strings = Arrays.asList(dealUserIds);
				List<String> collect = null;
				if(strings != null && strings.size() > 0){
					QueryWrapper<DealUserAccounts> dealQueryWrapper = new QueryWrapper<DealUserAccounts>();
					dealQueryWrapper.select("DEAL_ACCOUNT_ID").isNotNull("DEAL_ACCOUNT_ID");
					dealQueryWrapper.in("DEAL_USERID",strings);
					List<DealUserAccounts> dealList = dealUserAccountsService.list(dealQueryWrapper);
					collect = dealList.stream().map(DealUserAccounts::getDealAccountId).collect(Collectors.toList());
				}
				queryWrapper.in(IntCwDetailView::getDealAccountId, collect);
			}

			if(StringUtils.isNotEmpty(spid)) {
				queryWrapper.eq(IntCwDetailView::getSpid, spid);
			}
			if(StringUtils.isNotEmpty(theMonth)){
				queryWrapper.eq(IntCwDetailView::getThemonth, theMonth);
			}
			if(isFlag != null){
				queryWrapper.eq(IntCwDetailView::getFlagRender, isFlag);
			}
			if(dealType != null){
				queryWrapper.eq(IntCwDetailView::getDealTypeid, dealType);
			}
			if(StringUtils.isNotEmpty(startTime)) {
				int startDate = Integer.valueOf(startTime);
				queryWrapper.ge(IntCwDetailView::getThemonth, startDate);
			}
			if(StringUtils.isNotEmpty(endTime)) {
				int endDate = Integer.valueOf(endTime);
				queryWrapper.le(IntCwDetailView::getThemonth, endDate);
			}
		}
		List<IntCwDetailView> list = intCwDetailViewService.list(queryWrapper.orderByDesc(IntCwDetailView::getThemonth));
		// Http 1.0 header
        response.setDateHeader("Expires", 0);
        response.addHeader("Pragma", "no-cache");
        // Http 1.1 header
        response.setHeader("Cache-Control", "no-cache");
        String encodedfileName = new String(("结算明细单").getBytes("GBK"), "ISO8859-1");
        response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedfileName + ".pdf\"");
		response.setContentType("application/vnd.ms-pdf");

		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		pdfExportService.createReadyPdf(list, baos);
		response.getOutputStream().write(baos.toByteArray());
		response.getOutputStream().flush();
	}

	public class QueryHandler implements Callable<List<DateRangeUsersExcel>>{

		private int pageIndex;
		private LambdaQueryWrapper<DateRangeUsers> queryWrapper;

		public QueryHandler(int pageIndex, LambdaQueryWrapper<DateRangeUsers> queryWrapper) {
			this.pageIndex = pageIndex;
			this.queryWrapper = queryWrapper;
		}

		@Override
		public List<DateRangeUsersExcel> call() {
			long startTime = System.currentTimeMillis();
			Page<DateRangeUsers> pageResult = dateRangeUsersService.page(new Page<DateRangeUsers>(pageIndex, batchSize, false), queryWrapper);
			List<DateRangeUsersExcel> userList = new ArrayList<DateRangeUsersExcel>(batchSize);
			pageResult.getRecords().forEach(item -> userList.add(BeanUtil.copyProperties(item, DateRangeUsersExcel.class)));
			log.info("queryOracle| pageNum: "+pageIndex+", pageSize:"+batchSize+", cost:" + (System.currentTimeMillis() - startTime) + "ms");
			return userList;
		}
	}

	/**
	 *
	 * @param dateStr
	 * @return 0 - 无效； 1 - 日期； 2 - 月份
	 */
	private static int parseDateString(String dateStr) {
//		try {
//			DateTimeFormatter.ofPattern("yyyy-MM-dd").parse(dateStr);
//			return 1; //Integer.valueOf(dateStr.replaceAll("\\-", ""));
//		} catch (Exception e) {}
		try {
			DateTimeFormatter.ofPattern("yyyy-MM").parse(dateStr);
			return 2; //Integer.valueOf(dateStr.replaceAll("\\-", ""));
		} catch (Exception e) {}
		return 0;
	}


	@Value("${blade.file.uploadPath}")
	private String picDir;


	/**
	 * 导出结算表
	 * @param dealUserid
	 * @param spid
	 * @param queryDate
	 * @param response
	 * @throws Exception
	 */
	@GetMapping("/beforeChrist/export")
	@ApiOperation(value = "导出结算表BC")
	@ApiImplicitParams({
		@ApiImplicitParam(name = "sIds", value = "多选导出传递多个sid", required = false),
		@ApiImplicitParam(name = "dealUserid", value = "结算用户ID，逗号隔开。全部渠道传空或者不传递", required = false),
		@ApiImplicitParam(name = "spid", value = "产品ID", dataType = "string", required = false),
		@ApiImplicitParam(name = "startTime", value = "开始月份(格式：yyyyMM)", dataType = "string", required = false),
		@ApiImplicitParam(name = "endTime", value = "结束月份(格式：yyyyMM)", dataType = "string", required = false)
	})
	public R beforeChristExport(String[] sIds,String[] dealUserid, String spid,  String startTime,String endTime, HttpServletResponse response) throws Exception {
		LambdaQueryWrapper<DateRangeAccount> queryWrapper = Wrappers.<DateRangeAccount>lambdaQuery();
		if(dealUserid != null && dealUserid.length > 0) {
			List<String> strings = Arrays.asList(dealUserid);
			List<String> collect = null;
			if(strings != null && strings.size() > 0){
				QueryWrapper<DealUserAccounts> dealQueryWrapper = new QueryWrapper<DealUserAccounts>();
				dealQueryWrapper.select("DEAL_ACCOUNT_ID").isNotNull("DEAL_ACCOUNT_ID");
				dealQueryWrapper.in("DEAL_USERID",strings);
				List<DealUserAccounts> dealList = dealUserAccountsService.list(dealQueryWrapper);
				collect = dealList.stream().map(DealUserAccounts::getDealAccountId).collect(Collectors.toList());
			}
			queryWrapper.in(DateRangeAccount::getDealAccountId, collect);
		}
		if(StringUtils.isNotEmpty(spid)) {
			queryWrapper.eq(DateRangeAccount::getSpid, spid);
		}
		if(StringUtils.isNotEmpty(startTime) && parseDateString(startTime) != 0) {
			int startDate = Integer.valueOf(startTime.replaceAll("\\-", ""));
			queryWrapper.ge(DateRangeAccount::getTheMonth, startDate);
		}
		if(StringUtils.isNotEmpty(endTime) && parseDateString(endTime) != 0) {
			int endDate = Integer.valueOf(endTime.replaceAll("\\-", ""));
			queryWrapper.le(DateRangeAccount::getTheMonth, endDate);
		}

		//不包括本月数据
		Integer thisMonth = Integer.valueOf(DateTimeFormatter.ofPattern("yyyyMM").format(LocalDate.now()));
		queryWrapper.lt(DateRangeAccount::getTheMonth, thisMonth);

		List<DateRangeAccount> dbAccountList = null;
		if(sIds != null && sIds.length > 0) {
			dbAccountList = dateRangeAccountService.list(new LambdaQueryWrapper<DateRangeAccount>()
				.in(DateRangeAccount::getSid, Arrays.asList(sIds))
			);
		}else {
			dbAccountList = dateRangeAccountService.list(queryWrapper.orderByDesc(DateRangeAccount::getTheMonth, DateRangeAccount::getChannelId));
		}

		List<DateRangeAccountExcel> accountList = new ArrayList<DateRangeAccountExcel>();
		if(dbAccountList != null && !dbAccountList.isEmpty()) {
			dbAccountList.forEach(item -> accountList.add(BeanUtil.copyProperties(item, DateRangeAccountExcel.class)));
		}
		Long userId = SecureUtil.getUserId();
		UserModel byId = userService.getById(userId);
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddhhmmss");
		String format = simpleDateFormat.format(new Date());
		String tempFileName = byId.getRealName() + "-结算表" + format + RandomUtil.randomString(2) + ".xlsx";

		BladeReportTask bladeReportTask = new BladeReportTask();
		bladeReportTask.setReportName(tempFileName);
		bladeReportTask.setReportType(2);
		bladeReportTask.setReportStatus(1);
		bladeReportTask.setDownloadStatus(1);
		bladeReportTask.setCreateUser(userId);
		bladeReportTask.setCreateTime(new Date());
		boolean res = bladeReportTaskService.save(bladeReportTask);
		String filePath = picDir + tempFileName;
		Long beginTime = System.currentTimeMillis();
		if(res){
			new Thread(new Runnable() {
				@Override
				public void run() {
					try {
						//String filePath = "D:/boyuan/work2/excel/" + tempFileName;
						EasyExcel.write(filePath, DateRangeAccountExcel.class).sheet().doWrite(accountList);
						Long endTime = System.currentTimeMillis();
						String opetime = (endTime - beginTime) + "ms";
						bladeReportTask.setUseTime(opetime);
						bladeReportTask.setReportUrl("uploads/" + tempFileName);
						bladeReportTask.setReportStatus(2);
						bladeReportTask.setDownloadStatus(1);
						bladeReportTaskService.updateById(bladeReportTask);
					} catch (Exception e) {
						bladeReportTask.setReportStatus(3);
						bladeReportTask.setDownloadStatus(1);
						bladeReportTaskService.updateById(bladeReportTask);
						e.printStackTrace();
					}
				}
			}).start();
		}else {
			bladeReportTask.setReportStatus(3);
			bladeReportTaskService.updateById(bladeReportTask);
			return R.fail("导出任务提交失败");
		}
		return R.success("导出任务提交成功");
	}

	/**
	 * @param dealUserid
	 * @param spid
	 * @throws Exception
	 */
	@GetMapping("/detail/beforeChrist/export")
	@ApiOperation(value = "导出结算清单BC")
	@ApiImplicitParams({
		@ApiImplicitParam(name = "sIds", value = "多选导出传递多个sid", required = false),
		@ApiImplicitParam(name = "dealUserid", value = "结算用户ID，逗号隔开。全部渠道传空或者不传递", required = false),
		@ApiImplicitParam(name = "spid", value = "产品ID", dataType = "string", required = false),
		@ApiImplicitParam(name = "startTime", value = "开始月份(格式：yyyyMM)", dataType = "string", required = false),
		@ApiImplicitParam(name = "endTime", value = "结束月份(格式：yyyyMM)", dataType = "string", required = false)
	})
	public R beforeChristExportDetail(String[] sIds,String[] dealUserid, String spid, String startTime,String endTime, HttpServletResponse response) throws Exception {
		LambdaQueryWrapper<DateRangeUsers> userQueryWrapper = Wrappers.<DateRangeUsers>lambdaQuery();
		if(dealUserid != null && dealUserid.length > 0) {
			List<String> strings = Arrays.asList(dealUserid);
			List<String> collect = null;
			if(strings != null && strings.size() > 0){
				QueryWrapper<DealUserAccounts> dealQueryWrapper = new QueryWrapper<DealUserAccounts>();
				dealQueryWrapper.select("DEAL_ACCOUNT_ID").isNotNull("DEAL_ACCOUNT_ID");
				dealQueryWrapper.in("DEAL_USERID",strings);
				List<DealUserAccounts> dealList = dealUserAccountsService.list(dealQueryWrapper);
				collect = dealList.stream().map(DealUserAccounts::getDealAccountId).collect(Collectors.toList());
			}
			userQueryWrapper.in(DateRangeUsers::getDealAccountId, collect);
		}

		if(StringUtils.isNotEmpty(spid)) {
			userQueryWrapper.eq(DateRangeUsers::getSpid, spid);
		}
		if(StringUtils.isNotEmpty(startTime) && parseDateString(startTime) != 0) {
			int startDate = Integer.valueOf(startTime.replaceAll("\\-", ""));
			userQueryWrapper.ge(DateRangeUsers::getTheMonth, startDate);
		}
		if(StringUtils.isNotEmpty(endTime) && parseDateString(endTime) != 0) {
			int endDate = Integer.valueOf(endTime.replaceAll("\\-", ""));
			userQueryWrapper.le(DateRangeUsers::getTheMonth, endDate);
		}

		//不包括本月数据
		Integer thisMonth = Integer.valueOf(DateTimeFormatter.ofPattern("yyyyMM").format(LocalDate.now()));
		userQueryWrapper.lt(DateRangeUsers::getTheMonth, thisMonth);
		//设置排序条件
		userQueryWrapper.orderByDesc(DateRangeUsers::getTheMonth, DateRangeUsers::getOrderTime);

		LambdaQueryWrapper<DateRangeUsers> sidQueryWrapper = Wrappers.<DateRangeUsers>lambdaQuery();

		StringBuffer monthBef = new StringBuffer();
		StringBuffer channelBef = new StringBuffer();
		StringBuffer spidBef = new StringBuffer();

		String monthStr = "";
		String channelStr = "";
		String spidStr = "";
		List<DateRangeAccount> dbAccountList = null;
		int count = 0;
		if(sIds != null && sIds.length > 0) {
			dbAccountList = dateRangeAccountService.list(new LambdaQueryWrapper<DateRangeAccount>()
				.in(DateRangeAccount::getSid, Arrays.asList(sIds))
			);

			if(dbAccountList != null && dbAccountList.size() > 0){
				for (DateRangeAccount dateRangeAccount : dbAccountList) {
					monthBef.append(dateRangeAccount.getTheMonth()).append(",");
					channelBef.append(dateRangeAccount.getChannelId()).append(",");
					spidBef.append(dateRangeAccount.getSpid()).append(",");
				}
			}

			String mb = monthBef.toString();
			String cb = channelBef.toString();
			String sb = spidBef.toString();
			if(StringUtils.isNotBlank(mb)){
				monthStr = mb.substring(0,mb.length() - 1);
			}
			if(StringUtils.isNotBlank(cb)){
				channelStr = cb.substring(0,cb.length() - 1);
			}
			if(StringUtils.isNotBlank(sb)){
				spidStr = sb.substring(0,sb.length() - 1);
			}

			sidQueryWrapper.in(DateRangeUsers::getTheMonth, Arrays.asList(monthStr.split(",")));
			sidQueryWrapper.in(DateRangeUsers::getChannelId, Arrays.asList(channelStr.split(",")));
			sidQueryWrapper.in(DateRangeUsers::getSpid, Arrays.asList(spidStr.split(",")));

			count = dateRangeUsersService.count(sidQueryWrapper);
		}else {
			count = dateRangeUsersService.count(userQueryWrapper);
		}
		if(count >= 1000000){
			return R.fail("导出数据不能超出100万条");
		}

		Long userId = SecureUtil.getUserId();
		UserModel byId = userService.getById(userId);
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddhhmmss");
		String format = simpleDateFormat.format(new Date());
		String tempFileName = byId.getRealName() + "-结算清单表" + format + RandomUtil.randomString(2) + ".xlsx";

		BladeReportTask bladeReportTask = new BladeReportTask();
		bladeReportTask.setReportName(tempFileName);
		bladeReportTask.setReportType(2);
		bladeReportTask.setReportStatus(1);
		bladeReportTask.setDownloadStatus(1);
		bladeReportTask.setCreateUser(userId);
		bladeReportTask.setCreateTime(new Date());
		boolean res = bladeReportTaskService.save(bladeReportTask);
		String filePath = picDir + tempFileName;
		Long beginTime = System.currentTimeMillis();
		if(res){
			new Thread(new Runnable() {
				@Override
				public void run() {
					try {
						List<DateRangeUsers> list = null;
						if(sIds != null && sIds.length > 0) {
							list = dateRangeUsersService.list(sidQueryWrapper);
						}else {
							list = dateRangeUsersService.list(userQueryWrapper);
						}

						List<DateRangeUsersExcel> accountList = new ArrayList<DateRangeUsersExcel>();
						if(list != null && !list.isEmpty()) {
							list.forEach(item -> accountList.add(BeanUtil.copyProperties(item, DateRangeUsersExcel.class)));
						}
						//String filePath = "D:/boyuan/work2/excel/" + tempFileName;
						//EasyExcel.write(filePath, DateRangeAccountExcel.class).sheet().doWrite(accountList);
						EasyExcel.write(filePath, DateRangeUsersExcel.class).sheet().doWrite(accountList);
						Long endTime = System.currentTimeMillis();
						String opetime = (endTime - beginTime) + "ms";
						bladeReportTask.setUseTime(opetime);
						bladeReportTask.setReportStatus(2);
						bladeReportTask.setDownloadStatus(1);
						bladeReportTask.setReportUrl("uploads/" + tempFileName);
						bladeReportTaskService.updateById(bladeReportTask);
					} catch (Exception e) {
						bladeReportTask.setReportStatus(3);
						bladeReportTask.setDownloadStatus(1);
						bladeReportTaskService.updateById(bladeReportTask);
						e.printStackTrace();
					}
				}
			}).start();
		}else {
			bladeReportTask.setReportStatus(3);
			bladeReportTaskService.updateById(bladeReportTask);
			return R.fail("导出任务提交失败");
		}
		return R.success("导出任务提交成功");
	}

}
