package org.springblade.customer.controller;


import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.customer.dto.FctCsIrregularDTO;
import org.springblade.customer.dto.FctCsIrregularMoneyDTO;
import org.springblade.customer.dto.FctCsRecordsDTO;
import org.springblade.customer.dto.FctPrmViolationDTO;
import org.springblade.customer.entity.CustomerReport;
import org.springblade.customer.entity.CustomerReportCategory;
import org.springblade.customer.entity.FctCsIrregularMoney;
import org.springblade.customer.entity.FctCsRecords;
import org.springblade.customer.entity.FctPrmViolation;
import org.springblade.customer.enums.ImportsEnum;
import org.springblade.customer.enums.RedisKeyImports;
import org.springblade.customer.listener.FctCsIrregularListener;
import org.springblade.customer.listener.FctCsIrregularMoneyListener;
import org.springblade.customer.listener.FctCsRecordsListener;
import org.springblade.customer.listener.FctPrmViolationListener;
import org.springblade.customer.service.ICustomerReportCategoryService;
import org.springblade.customer.service.ICustomerReportService;
import org.springblade.customer.service.IFctCsIrregularMoneyService;
import org.springblade.customer.service.IFctCsIrregularService;
import org.springblade.customer.service.IFctCsRecordsService;
import org.springblade.customer.service.IFctPrmViolationService;
import org.springblade.system.client.UserClient;
import org.springblade.system.client.model.UserModel;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import cn.hutool.core.util.RandomUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author zbc
 * @since 2021-03-22
 */
@RestController
@AllArgsConstructor
@Slf4j
@RequestMapping("customer/imports")
@Api(value = "客服数据导入", tags = "客服数据导入")
public class ImportsController extends BladeController {


	/**
	 * 客服投诉明细
	 */
	@Autowired
	private IFctCsIrregularService fctCsIrregularService;

	/**
	 * 呼叫中心
	 */
	@Autowired
	private IFctCsRecordsService fctCsRecordsService;

	/**
	 * PRM违约明细
	 */
	@Autowired
	private IFctPrmViolationService fctPrmViolationService;

	/**
	 * 不规范扣款
	 */
	@Autowired
	private IFctCsIrregularMoneyService fctCsIrregularMoneyService;

	@Autowired
	private ICustomerReportService customerReportService;

	@Autowired
	private ICustomerReportCategoryService customerReportCategoryService;

	@Autowired
	private UserClient userService;

	@Autowired
	private BladeRedis redisService;

	private static final Pattern MONEY_PATTERN = Pattern.compile("^(([1-9]{1}\\d*)|([0]{1}))(\\.(\\d){0,2})?$");


	@PostMapping("/entrance")
	@ApiOperation(value = "报表导入", notes = "报表导入")
	public R entrance(@RequestParam(required = true, name = "file") MultipartFile file,
					  @RequestParam(required = true, name = "excelCode") String excelCode,
					  @RequestParam(required = true, name = "reportUrl") String reportUrl
	) {
		if (file == null) {
			return R.fail("导入文件不能为空");
		}
		if (StringUtils.isBlank(excelCode)) {
			return R.fail("excelCode不能为空");
		}
		if (StringUtils.isBlank(reportUrl)) {
			return R.fail("reportUrl不能为空");
		}
		Long beginTime = System.currentTimeMillis();
		//客服投诉明细报表导入
		String batchNum = RandomUtil.randomString(10);
		if (ImportsEnum.FCT_KS.getCode().equals(excelCode)) {
			return FctCsIrregularImport(file, beginTime,reportUrl,excelCode,batchNum);
		}
		//呼叫中心报表导入
		if (ImportsEnum.FCT_HJ.getCode().equals(excelCode)) {
			return FctCsRecordsImport(file, beginTime,reportUrl,excelCode,batchNum);
		}
		//PRM违约明细报表导入
		if (ImportsEnum.FCT_WY.getCode().equals(excelCode)) {
			return FctPrmViolationImport(file, beginTime,reportUrl,excelCode,batchNum);
		}
		//不规范扣款报表导入
		if (ImportsEnum.FCT_KK.getCode().equals(excelCode)) {
			return FctCsIrregularMoneyImport(file, beginTime,reportUrl,excelCode,batchNum);
		}
		return R.fail("excelCode 参数异常");
	}


	/**
	 * 客服投诉明细报表导入
	 * @param file
	 * @return
	 */
	private R FctCsIrregularImport(MultipartFile file, Long beginTime,String reportUrl,String excelCode,String batchNum) {
		FctCsIrregularListener easyExcelListener = new FctCsIrregularListener();
		List<FctCsIrregularDTO> excelList = easyExcelListener.list;
		try {
			InputStream inputStream = file.getInputStream();
			EasyExcel.read(inputStream, FctCsIrregularDTO.class, easyExcelListener).sheet().doRead();
			log.info("导入条数" + excelList.size());
			for (FctCsIrregularDTO fctCsIrregularDTO : excelList) {
				fctCsIrregularDTO.setBatchNum(batchNum);
			}
			String sTime = "";
			String eTime = "";
			//清除同月份旧数据，以结单时间为准，精确到月
			SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
			SimpleDateFormat simple = new SimpleDateFormat("yyyyMMdd");
			String finishTime = excelList.get(0).getFinishTime();
			String spcode = excelList.get(0).getSpcode();
			try {
				Date time = format.parse(finishTime);
				Calendar cale = Calendar.getInstance();
				cale.setTime(time);
				cale.set(Calendar.DAY_OF_MONTH,1);
				sTime = simple.format(cale.getTime());
				cale.set(Calendar.DAY_OF_MONTH,cale.getActualMaximum(Calendar.DAY_OF_MONTH));
				eTime = simple.format(cale.getTime());
				boolean del = fctCsIrregularService.deleteOldData(sTime,eTime,spcode);
				log.info("不规范定制（投诉明细）数据 清除旧数据结果 {}",del);
			}catch (Exception e){
				e.printStackTrace();
			}
			boolean fct = fctCsIrregularService.insertBatch(excelList);
			if (fct) {
				//根据导入的产品代码设置spid
				fctCsIrregularService.setSpid();
				log.info("根据导入的产品代码设置spid 执行完毕");

				//根据结单时间设定日期字段
				fctCsIrregularService.setTheday();
				log.info("根据结单时间设定日期字段 执行完毕");

				//清除状态字段中的不可见字符(有效)
				fctCsIrregularService.deleteInvisibleDatay(sTime,eTime);
				log.info("清除状态字段中的不可见字符(有效) 执行完毕");

				//清除状态字段中的不可见字符(无效)
				fctCsIrregularService.deleteInvisibleDataw(sTime,eTime);
				log.info("清除状态字段中的不可见字符(无效) 执行完毕");

				//清除状态字段中的不可见字符(申诉中)
				fctCsIrregularService.deleteInvisibleDatas(sTime,eTime);
				log.info("清除状态字段中的不可见字符(申诉中) 执行完毕");
				try {
					//生成统计数据1
					fctCsIrregularService.callData1(sTime);
					log.info("生成统计数据1 执行完毕");

					//生成统计数据2
					fctCsIrregularService.callData12(sTime.substring(0,6));
					log.info("生成统计数据2 执行完毕");

				}catch (Exception e){
					e.printStackTrace();
				}
				//存储客服报表信息
				String fileName = file.getOriginalFilename();
				subCustomerReport(fileName,reportUrl,excelCode,batchNum);
				HashMap<String, Object> resultMap = new HashMap<>();
				Long endTime = System.currentTimeMillis();
				String opetime = (endTime - beginTime) + "ms";
				resultMap.put("fileName", fileName);
				resultMap.put("num", excelList.size());
				resultMap.put("time", opetime);
				return R.data(resultMap);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return R.fail("导入失败");
	}



	/**
	 * 呼叫中心报表导入
	 * @param file
	 * @return
	 */
	private R FctCsRecordsImport(MultipartFile file, Long beginTime,String reportUrl,String excelCode,String batchNum) {
		FctCsRecordsListener easyExcelListener = new FctCsRecordsListener();
		List<FctCsRecordsDTO> excelList = easyExcelListener.list;
		try {
			InputStream inputStream = file.getInputStream();
			EasyExcel.read(inputStream, FctCsRecordsDTO.class, easyExcelListener).sheet().doRead();
			log.info("导入条数" + excelList.size());
			List<FctCsRecords> voList = new ArrayList<FctCsRecords>();
			SimpleDateFormat simple = new SimpleDateFormat("yyyyMMdd");
			if (excelList != null && !excelList.isEmpty()) {
				for (FctCsRecordsDTO obj : excelList) {
					try {
						FctCsRecords bean = new FctCsRecords();
						BeanUtils.copyProperties(obj, bean);
						bean.setBatchNum(batchNum);
						//受理时间处理
						if (StringUtils.isNotBlank(obj.getAcceptTime())) {
							bean.setAcceptTime(sysDate(obj.getAcceptTime()));
							bean.setTheday(Long.valueOf(simple.format(sysDate(obj.getAcceptTime()))));
						}
						//受理号码处理
						if (StringUtils.isNotBlank(obj.getAcceptPhonenum())) {
							String regEx = "[\n`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。， ·、？]";
							String regEx_cha = "[\u4e00-\u9fa5]";
							String replace = "";
							String trim = obj.getAcceptPhonenum().replaceAll(regEx, replace).trim();
							String trim_cha = trim.replaceAll(regEx_cha, replace).trim();
							if(trim_cha.length() <= 11){
								bean.setAcceptPhonenum(trim_cha);
							}else {
								bean.setAcceptPhonenum(trim_cha.substring(0,11));
							}
						}
						//工单类型处理
						if (StringUtils.isNotBlank(obj.getComplaintType())) {
							if(obj.getComplaintType().startsWith("办理")){
								bean.setComplaintType("办理");
							}else if(obj.getComplaintType().startsWith("咨询")){
								bean.setComplaintType("咨询");
							}else if(obj.getComplaintType().startsWith("投诉")){
								bean.setComplaintType("投诉");
							}else {
								bean.setComplaintType(obj.getComplaintType().length() >= 10 ? obj.getComplaintType().substring(0,10):obj.getComplaintType());
							}
						}
						//退费金额处理
						if (StringUtils.isNotBlank(obj.getRefundMoney())) {
							String regEx_cha = "[\u4e00-\u9fa5]";
							String replace = "";
							String trim_cha = obj.getRefundMoney().replaceAll(regEx_cha, replace).trim();
							String money = trim_cha.replaceAll(",", replace);
							bean.setRefundMoney(Double.valueOf(money));
						}
						//完结时间处理
						if (StringUtils.isNotBlank(obj.getFinishTime())) {
							bean.setFinishTime(sysDate(obj.getFinishTime()));
						}
						voList.add(bean);
					} catch (Exception e) {
						e.printStackTrace();
						log.info("obj = {}",obj);
					}
				}
			}

			//清除同月份旧数据
			SimpleDateFormat format = new SimpleDateFormat("yyyyMM");
			Date acceptTime = voList.get(0).getAcceptTime();
			String month = format.format(acceptTime);
			boolean rem = fctCsRecordsService.removeThisMonthData(month);
			log.info("呼叫中心清除同月份旧数据 执行结果 {}",rem);

			boolean fct = fctCsRecordsService.saveBatch(voList);
			if (fct) {
				//根据导入的受理时间设置日期字段
				fctCsRecordsService.setThedayByAcceptTime();
				log.info("根据导入的受理时间设置日期字段 执行完毕");

				//从业务类型列提取spcode字段
				fctCsRecordsService.setSpcode();
				log.info("从业务类型列提取spcode字段 执行完毕");

				//根据导入的业务种类名称设置适用于经分报告统计的业务种类字段 – 1
				fctCsRecordsService.setServiceType31();
				log.info("根据导入的业务种类名称设置适用于经分报告统计的业务种类字段 – 1 执行完毕");

				//根据导入的业务种类名称设置适用于经分报告统计的业务种类字段 – 2
				fctCsRecordsService.setServiceType32();
				log.info("根据导入的业务种类名称设置适用于经分报告统计的业务种类字段 - 2 执行完毕");

				Calendar cale = Calendar.getInstance();
				cale.setTime(acceptTime);
				cale.set(Calendar.DAY_OF_MONTH,1);
				String sTime = simple.format(cale.getTime());

				cale.set(Calendar.DAY_OF_MONTH,cale.getActualMaximum(Calendar.DAY_OF_MONTH));
				String eTime = simple.format(cale.getTime());
				log.info("sTime = {} eTime = {}",sTime,eTime);
				//--根据业务名称，从产品表匹配spid。（用月份拼接‘01’、‘31’来生成SQL中的日期）
				fctCsRecordsService.setSpidByThisMonth(sTime,eTime);
				log.info("根据业务名称，从产品表匹配当月spid 执行完毕");

				//部分产品名称与字典表不一致的数据，另行设定spid
				fctCsRecordsService.setOtherSpidByThisMonth(sTime,eTime);
				log.info("部分产品名称与字典表不一致的数据，另行设定spid 执行完毕");

				//-根据spid设定产品短名称
				fctCsRecordsService.setShortName(sTime,eTime);
				log.info("根据spid设定产品短名称 执行完毕");

				//没有从字典表关联到短名称的产品，默认设置短名称与产品名称相同
				fctCsRecordsService.setShopName(sTime,eTime);
				log.info("没有从字典表关联到短名称的产品，默认设置短名称与产品名称相同 执行完毕");

				try {
					//生成统计结果
					fctCsRecordsService.callData(sTime);
					log.info("生成统计结果 执行完毕");
				}catch (Exception e){
					e.printStackTrace();
				}

				HashMap<String, Object> resultMap = new HashMap<>();
				Long endTime = System.currentTimeMillis();
				String fileName = file.getOriginalFilename();
				subCustomerReport(fileName,reportUrl,excelCode,batchNum);
				String opetime = (endTime - beginTime) + "ms";
				resultMap.put("fileName", fileName);
				resultMap.put("num", excelList.size());
				resultMap.put("time", opetime);
				return R.data(resultMap);
			} else {
				return R.fail("导入失败");
			}
		} catch (Exception e) {
			e.printStackTrace();
			return R.fail("导入失败");
		}
	}

	private Date sysDate(String time) {
		String format = "yyyy-MM-dd";
		String format1 = "yyyy-MM-dd HH:mm:ss";
		SimpleDateFormat simple = null;
		if(time.replaceAll("\\s*", "").length() == format.replaceAll("\\s*", "").length()){
			simple = new SimpleDateFormat(format);
		}else if(time.replaceAll("\\s*", "").length() == format1.replaceAll("\\s*", "").length()){
			simple = new SimpleDateFormat(format1);
		}
		try {
			Date parse = simple.parse(time);
			return parse;
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}


	/**
	 * PRM违约明细报表导入
	 * @param file
	 * @return
	 */
	private R FctPrmViolationImport(MultipartFile file, Long beginTime,String reportUrl,String excelCode,String batchNum) {
		FctPrmViolationListener easyExcelListener = new FctPrmViolationListener();
		List<FctPrmViolationDTO> excelList = easyExcelListener.list;
		String fileName = file.getOriginalFilename();

		List<CustomerReport> olist = customerReportService.list(new LambdaQueryWrapper<CustomerReport>()
			.eq(CustomerReport::getReportName, fileName)
		);
		if(olist != null && olist.size() > 0){
			return fail("该文件不能重复导入");
		}
		try {
			InputStream inputStream = file.getInputStream();
			EasyExcel.read(inputStream, FctPrmViolationDTO.class, easyExcelListener).sheet().doRead();
			log.info("导入条数" + excelList.size());
			List<FctPrmViolation> voList = new ArrayList<FctPrmViolation>();
			if (excelList != null && !excelList.isEmpty()) {
				SimpleDateFormat format = new SimpleDateFormat("yyyyMM");
				voList = excelList.stream()
					.map(obj -> {
						FctPrmViolation bean = new FctPrmViolation();
						BeanUtils.copyProperties(obj, bean);
						bean.setBatchNum(batchNum);
						bean.setDtype("MONTH");
						//违约审批月份
						if (StringUtils.isNotBlank(obj.getViolationApproveMonth())) {
							String replace = obj.getViolationApproveMonth().replace("年", "").replace("月", "");
							Date parse = null;
							try {
								parse = format.parse(replace);
							} catch (ParseException e) {
								e.printStackTrace();
							}
							bean.setThedvalue(Long.valueOf(format.format(parse)));
						}
						//扣款
						if (StringUtils.isNotBlank(obj.getDeductMoney())) {
							String money = obj.getDeductMoney().replaceAll(",", "");
							bean.setDeductMoney(Double.valueOf(money));
						}
						return bean;
					}).collect(Collectors.toList());
			}
			boolean fct = fctPrmViolationService.saveBatch(voList);
			if (fct) {
				HashMap<String, Object> resultMap = new HashMap<>();
				Long endTime = System.currentTimeMillis();
				String opetime = (endTime - beginTime) + "ms";
				subCustomerReport(fileName,reportUrl,excelCode,batchNum);
				resultMap.put("fileName", fileName);
				resultMap.put("num", excelList.size());
				resultMap.put("time", opetime);
				return R.data(resultMap);
			} else {
				return R.fail("导入失败");
			}
		} catch (Exception e) {
			e.printStackTrace();
			return R.fail("导入失败");
		}
	}

	/**
	 * 不规范扣款报表导入
	 * @param file
	 * @return
	 */
	private R FctCsIrregularMoneyImport(MultipartFile file, Long beginTime,String reportUrl,String excelCode,String batchNum) {
		FctCsIrregularMoneyListener easyExcelListener = new FctCsIrregularMoneyListener();
		List<FctCsIrregularMoneyDTO> excelList = easyExcelListener.list;
		try {
			InputStream inputStream = file.getInputStream();
			EasyExcel.read(inputStream, FctCsIrregularMoneyDTO.class, easyExcelListener).sheet().doRead();
			log.info("导入条数" + excelList.size());

			String complaintMonth = excelList.get(0).getComplaintMonth();
			log.info("扣罚金额（PRM不规范定制扣款）投诉账期 {}",complaintMonth);
			boolean remove = fctCsIrregularMoneyService.remove(new LambdaQueryWrapper<FctCsIrregularMoney>()
				.eq(FctCsIrregularMoney::getSpcode, excelList.get(0).getSpcode())
				.eq(FctCsIrregularMoney::getComplaintMonth, complaintMonth)
			);
			log.info("清除同月份旧数据结果 {}",remove);

			List<FctCsIrregularMoney> voList = new ArrayList<FctCsIrregularMoney>();
			if (excelList != null && !excelList.isEmpty()) {
				for (FctCsIrregularMoneyDTO obj : excelList) {
					try {
						FctCsIrregularMoney bean = new FctCsIrregularMoney();
						BeanUtils.copyProperties(obj, bean);
						bean.setBatchNum(batchNum);
						//投诉账期
						if (StringUtils.isNotBlank(obj.getComplaintMonth())) {
							bean.setThemonth(Long.valueOf(obj.getComplaintMonth()));
							bean.setComplaintMonth(Long.valueOf(obj.getComplaintMonth()));
						}
						//扣款
						if (StringUtils.isNotBlank(obj.getMoney())) {
							String money = obj.getMoney().replaceAll(",", "");
							bean.setMoney(Double.valueOf(money));
						}
						voList.add(bean);
					}catch (Exception e){
						e.printStackTrace();
					}
				}
			}
			boolean fct = fctCsIrregularMoneyService.saveBatch(voList);
			if (fct) {
				try {
					//生成统计数据1
					fctCsIrregularMoneyService.setMoney1(complaintMonth);
					log.info("生成统计数据1 执行完毕");

					//生成统计数据2
					fctCsIrregularMoneyService.setMoney2(complaintMonth);
					log.info("生成统计数据2 执行完毕");

					//生成统计数据3
					fctCsIrregularMoneyService.setMoney3(complaintMonth);
					log.info("生成统计数据3 执行完毕");
				}catch (Exception e){
					e.printStackTrace();
				}

				redisService.set(RedisKeyImports.ENTRANCE_IMPORTS_KEY+excelCode, (batchNum + 9));
				HashMap<String, Object> resultMap = new HashMap<>();
				Long endTime = System.currentTimeMillis();
				String opetime = (endTime - beginTime) + "ms";
				String fileName = file.getOriginalFilename();
				subCustomerReport(fileName,reportUrl,excelCode,batchNum);
				resultMap.put("fileName", fileName);
				resultMap.put("num", excelList.size());
				resultMap.put("time", opetime);
				return R.data(resultMap);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return R.fail("导入失败");
	}

	private void subCustomerReport(String fileName,String reportUrl,String excelCode,String batchNum) {
		CustomerReportCategory one = customerReportCategoryService.getOne(new LambdaQueryWrapper<CustomerReportCategory>()
			.eq(CustomerReportCategory::getCategoryCode, excelCode)
			.last("limit 1")
		);
		BladeUser bladeUser = AuthUtil.getUser();
		UserModel user = userService.getById(bladeUser.getUserId());
		CustomerReport customerReport = new CustomerReport();
		customerReport.setReportName(fileName);
		customerReport.setCategoryCode(excelCode);
		customerReport.setCategoryId(one.getId());
		customerReport.setReportUrl(reportUrl);
		customerReport.setCreateUser(user.getName());
		customerReport.setCreateTime(new Date());
		customerReport.setBatchNum(batchNum);
		customerReportService.save(customerReport);
	}




}

