package cn.superdesk.uniorder.controller.accounting.customer;


import cn.superdesk.libs.common.json.JsonUtils;
import cn.superdesk.libs.common.util.CollectionUtils;
import cn.superdesk.uniorder.common.R;
import cn.superdesk.uniorder.common.enums.credit.UnifiedOrderCreditBackStatusEnum;
import cn.superdesk.uniorder.common.enums.credit.UnifiedOrderCreditInvoiceApplyStatusEnum;
import cn.superdesk.uniorder.common.enums.credit.UnifiedOrderCreditInvoiceMakeStatusEnum;
import cn.superdesk.uniorder.common.enums.order.UnifiedOrderAccountingStateEnum;
import cn.superdesk.uniorder.controller.base.BaseController;
import cn.superdesk.uniorder.dao.entity.accounting.score.customer.AccountingScoreCustomer;
import cn.superdesk.uniorder.dto.param.accounting.score.customer.AccountingScoreCustomerCreateParam;
import cn.superdesk.uniorder.dto.param.accounting.score.customer.AccountingScoreCustomerCreateSelectedCreditParam;
import cn.superdesk.uniorder.dto.vo.score.ScoreOrderReconciliationNotYetHeadVo;
import cn.superdesk.uniorder.dto.vo.score.ScoreOrderReconciliationNotYetVo;
import cn.superdesk.uniorder.dubbo.consumer.accounting.AccountingScoreCustomerDubboConsumerService;
import cn.superdesk.uniorder.dubbo.consumer.accounting.AccountingUnifiedCustomerDubboConsumerService;
import cn.superdesk.uniorder.dubbo.consumer.base.UnifiedOrderDubboConsumerService;
import cn.superdesk.uniorder.dubbo.consumer.invoice.InvoiceApplyDubboConsumerService;
import cn.superdesk.uniorder.dubbo.consumer.sys.SysConfigDubboConsumerService;
import cn.superdesk.uniorder.dubbo.consumer.sys.SysInvDubboConsumerService;
import cn.superdesk.uniorder.utils.excel.ExcelUtils;
import cn.superdesk.uniorder.utils.exception.ExceptionUtils;
import cn.superdesk.uniorder.utils.security.MyTools;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description: Java类作用描述
 * @Author: linjinyu
 * @CreateDate: 6/18/20 2:32 PM
 * @UpdateUser: linjinyu
 * @UpdateDate: 6/18/20 2:32 PM
 * @UpdateRemark: 修改内容
 * @Version: 1.0
 */
@Slf4j
@RestController
@RequestMapping("/accounting/score/customer/notyet")
public class ScoreCustomerNotYetController extends BaseController {

	@Autowired
	UnifiedOrderDubboConsumerService unifiedOrderDubboConsumerService;
	@Autowired
	InvoiceApplyDubboConsumerService invoiceApplyDubboConsumerService;


	@Autowired
	AccountingUnifiedCustomerDubboConsumerService accountingUnifiedCustomerDubboConsumerService;
	@Autowired
	AccountingScoreCustomerDubboConsumerService   accountingScoreCustomerDubboConsumerService;

	@Autowired
	SysConfigDubboConsumerService sysConfigDubboConsumerService;
	@Autowired
	SysInvDubboConsumerService    sysInvDubboConsumerService;
	@Autowired
	JavaMailSender                javaMailSender;

	@RequestMapping(value = "/getOrderReconciliationAll", method = RequestMethod.POST)
	@ResponseBody
	public R<List<ScoreOrderReconciliationNotYetVo>> getOrderReconciliationAll() {

		R<List<ScoreOrderReconciliationNotYetVo>> result = new R<>();

		try {

			// 筛选条件
			Map<String, Object> params = new HashMap<>();

//			xml id getScoreOrderReconciliationNotYet

//			---- 下单时间 so.create_time
			params.put("startTime", getString("startTime"));
			params.put("endTime", getString("endTime"));

//			---- 下单人姓名 so.purchase_user_name
			params.put("purchaseUserId", getLong("purchaseUserId"));
			params.put("purchaseUserName", getString("purchaseUserName"));
			params.put("purchasePhone", getString("purchasePhone"));

//			---- 订单编号 soc.order_sn
			params.put("orderSn", getString("orderSn"));

//			---- 企业名称 so.purchase_virt_name
			params.put("purchaseVirtId", getLong("purchaseVirtId"));
			params.put("purchaseVirtName", getString("purchaseVirtName"));

//			---- 积分类型 soc.credit_name
			params.put("creditName", getString("creditName"));

//			---- 积分批次 soc.batchs
			params.put("batchs", getString("batchs"));


			// 处理到这里 已经把 table list 的数据填充了
			result = unifiedOrderDubboConsumerService.getScoreOrderReconciliationNotYet(getToken(), params, getPageNum(), getPageSize());

			for (ScoreOrderReconciliationNotYetVo vo : result.getData()) {
				vo.setAccountingStateCustomerName(UnifiedOrderAccountingStateEnum.getDesc(vo.getAccountingStateCustomer()));

				vo.setInvoiceApplyStatusName(UnifiedOrderCreditInvoiceApplyStatusEnum.getDesc(vo.getInvoiceApplyStatus()));
				vo.setInvoiceMakeStatusName(UnifiedOrderCreditInvoiceMakeStatusEnum.getDesc(vo.getInvoiceMakeStatus()));
				vo.setBackStatusName(UnifiedOrderCreditBackStatusEnum.getDesc(vo.getBackStatus()));
			}


//			订单数：131 订单金额：¥ 117566.6 应收金额：¥ 99055 退货金额：¥ 18511.6
			ScoreOrderReconciliationNotYetHeadVo scoreOrderReconciliationNotYetHeadSum = unifiedOrderDubboConsumerService.getScoreOrderReconciliationNotYetHeadSum(getToken(), params);
//			unifiedOrderSupHE.setRealAmount(unifiedOrderSupHE.getOrderAmount());
//			unifiedOrderSupHE.setOrderAmount(unifiedOrderSupHE.getOrderAmount().add(unifiedOrderSupHE.getReturnAmount()));
//
			Map<String, Object> headData = new HashMap<>();
			// 订单金额：¥ 22
			headData.put("totalOrderSnNum", scoreOrderReconciliationNotYetHeadSum.getTotalOrderSnNum());
			// 订单数：1
			headData.put("totalGoodsIdNum", scoreOrderReconciliationNotYetHeadSum.getTotalGoodsIdNum());
			// 退货金额：¥ 0
			headData.put("totalBalanceAmount", scoreOrderReconciliationNotYetHeadSum.getTotalBalanceAmount());


			result.setHeadData(headData);

		} catch (Exception e) {

			result.setCode(String.valueOf(e.hashCode()));
			result.setSuccess(false);
			result.setMessage(e.getMessage());

			log.error(ExceptionUtils.getMessage(e));
			e.printStackTrace();
		}
		return result;
	}


	/***
	 * 积分结算(相当于客户结算)
	 * | ----> 积分结算 -> 未结算商品
	 *
	 * 原名字为 getnotdzpage
	 *
	 * @url http://localhost:8089/web/score/getOrderReconciliationNotYet
	 * @url http://localhost:8089/web/score/accounting/customer/getOrderReconciliationNotYet
	 *
	 * @return
	 */
	@RequestMapping(value = "/getOrderReconciliationNotYet", method = RequestMethod.POST)
	@ResponseBody
	public R<List<ScoreOrderReconciliationNotYetVo>> getOrderReconciliationNotYet() {

		R<List<ScoreOrderReconciliationNotYetVo>> result = new R<>();

		try {

			// 筛选条件
			Map<String, Object> params = new HashMap<>();

//			xml id getScoreOrderReconciliationNotYet

//			---- 下单时间 so.create_time
			params.put("startTime", getString("startTime"));
			params.put("endTime", getString("endTime"));

//			---- 下单人姓名 so.purchase_user_name
			params.put("purchaseUserId", getLong("purchaseUserId"));
			params.put("purchaseUserName", getString("purchaseUserName"));
			params.put("purchasePhone", getString("purchasePhone"));

//			---- 订单编号 soc.order_sn
			params.put("orderSn", getString("orderSn"));

//			---- 企业名称 so.purchase_virt_name
			params.put("purchaseVirtId", getLong("purchaseVirtId"));
			params.put("purchaseVirtName", getString("purchaseVirtName"));

//			---- 积分类型 soc.credit_name
			params.put("creditName", getString("creditName"));

//			---- 积分批次 soc.batchs
			params.put("batchs", getString("batchs"));

			//			<!-- 客户对账:1-已对账;2-未对账 只作用未结算流水 -->
			params.put("accountingStateCustomer", 2);


			// 处理到这里 已经把 table list 的数据填充了
			result = unifiedOrderDubboConsumerService.getScoreOrderReconciliationNotYet(getToken(), params, getPageNum(), getPageSize());

			for (ScoreOrderReconciliationNotYetVo vo : result.getData()) {
				vo.setAccountingStateCustomerName(UnifiedOrderAccountingStateEnum.getDesc(vo.getAccountingStateCustomer()));

				vo.setInvoiceApplyStatusName(UnifiedOrderCreditInvoiceApplyStatusEnum.getDesc(vo.getInvoiceApplyStatus()));
				vo.setInvoiceMakeStatusName(UnifiedOrderCreditInvoiceMakeStatusEnum.getDesc(vo.getInvoiceMakeStatus()));
				vo.setBackStatusName(UnifiedOrderCreditBackStatusEnum.getDesc(vo.getBackStatus()));
			}


//			订单数：131 订单金额：¥ 117566.6 应收金额：¥ 99055 退货金额：¥ 18511.6
			ScoreOrderReconciliationNotYetHeadVo scoreOrderReconciliationNotYetHeadSum = unifiedOrderDubboConsumerService.getScoreOrderReconciliationNotYetHeadSum(getToken(), params);
//			unifiedOrderSupHE.setRealAmount(unifiedOrderSupHE.getOrderAmount());
//			unifiedOrderSupHE.setOrderAmount(unifiedOrderSupHE.getOrderAmount().add(unifiedOrderSupHE.getReturnAmount()));
//
			Map<String, Object> headData = new HashMap<>();
			// 订单金额：¥ 22
			headData.put("totalOrderSnNum", scoreOrderReconciliationNotYetHeadSum.getTotalOrderSnNum());
			// 订单数：1
			headData.put("totalGoodsIdNum", scoreOrderReconciliationNotYetHeadSum.getTotalGoodsIdNum());
			// 退货金额：¥ 0
			headData.put("totalBalanceAmount", scoreOrderReconciliationNotYetHeadSum.getTotalBalanceAmount());


			result.setHeadData(headData);

		} catch (Exception e) {

			result.setCode(String.valueOf(e.hashCode()));
			result.setSuccess(false);
			result.setMessage(e.getMessage());

			log.error(ExceptionUtils.getMessage(e));
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 积分结算(相当于客户结算)
	 * | ----> 积分结算 -> 未结算流水 | 此页面是以商品流水的维度去展示的 opt 搜索 下单时间 只能以订单维度 最终
	 * | ----> | ----> TODO 导出表格
	 * getexcel
	 *
	 * @param response
	 * @throws IOException
	 */
	@RequestMapping(value = "/getOrderReconciliationNotYet2Excel", method = RequestMethod.GET)
	public void getOrderReconciliationNotYet2Excel(HttpServletResponse response) throws IOException {

		try {

			// 筛选条件
			Map<String, Object> params = new HashMap<>();

//			xml id getScoreOrderReconciliationNotYet

//			---- 下单时间 so.create_time
			params.put("startTime", getString("startTime"));
			params.put("endTime", getString("endTime"));

//			---- 下单人姓名 so.purchase_user_name
			params.put("purchaseUserId", getLong("purchaseUserId"));
			params.put("purchaseUserName", getString("purchaseUserName"));
			params.put("purchasePhone", getString("purchasePhone"));

//			---- 订单编号 soc.order_sn
			params.put("orderSn", getString("orderSn"));

//			---- 企业名称 so.purchase_virt_nameexportgoods
			params.put("purchaseVirtId", getLong("purchaseVirtId"));
			params.put("purchaseVirtName", getString("purchaseVirtName"));

//			---- 积分类型 soc.credit_name
			params.put("creditName", getString("creditName"));

//			---- 积分批次 soc.batchs
			params.put("batchs", getString("batchs"));

			// 处理到这里 已经把 table list 的数据填充了
			R<List<ScoreOrderReconciliationNotYetVo>> result = new R<>();
			result = unifiedOrderDubboConsumerService.getScoreOrderReconciliationNotYet(getToken(), params, getPageNum(), /*getPageSize()*/ 999999);


			for (ScoreOrderReconciliationNotYetVo vo : result.getData()) {
				vo.setAccountingStateCustomerName(UnifiedOrderAccountingStateEnum.getDesc(vo.getAccountingStateCustomer()));

				vo.setInvoiceApplyStatusName(UnifiedOrderCreditInvoiceApplyStatusEnum.getDesc(vo.getInvoiceApplyStatus()));
				vo.setInvoiceMakeStatusName(UnifiedOrderCreditInvoiceMakeStatusEnum.getDesc(vo.getInvoiceMakeStatus()));
				vo.setBackStatusName(UnifiedOrderCreditBackStatusEnum.getDesc(vo.getBackStatus()));
			}


//			String[] field = {"batchs", "creditName",
//					"goodsName", "orderSn", "accountingStateCustomerName", "price", "balance", "purchaseVirtName",
//					"purchaseUserName",
//					"purchasePhone", "createTime", "remarks"
//			};
//
//			String[] fieldZn = {"积分批次", "积分类型",
//					"商品名称", "订单编号", "结算状态", "商品销售价", "使用积分", "企业名称",
//					"下单人",
//					"下单人电话", "下单时间", "备注"};


			// 20200723 附件1：对账单导出格式与字段.xls
			String[] field = {"unifiedOrderCreditId", "outSnapshotOrderCreditId", "batchs", "orderSn", "purchaseVirtName", "purchaseUserName", "purchasePhone", "goodsName", "cateNameLv3", "price", "quantity", "totalPrice", "creditName", "balance", "balance",
					"fiscalCode", "taxCode", "taxRate",
					"createTime",
					"orderStateName", "saleName", "expressCompany", "expressSn", "updateTime",
					"accountingStateCustomerName", "invoiceApplyStatusName", "invoiceMakeStatusName", "backStatusName", "remarks"
			};

			String[] fieldZn = {"结算中心流水ID", "快照积分流水ID", "积分批次", "订单编号", "企业名称", "用户姓名", "手机号", "商品名称", "三级分类", "销售单价", "数量", "销售总价", "积分类型", "积分支付", "结算金额",
					"财务编码", "税务编码", "税率%",
					"下单时间",
					"订单状态", "供货方", "快递公司", "快递单号", "更新时间",
					"对账状态", "发票申请", "开票状态", "回款状态", "备注"
			};

			HSSFWorkbook workbook = ExcelUtils.createWorkbook(result.getData(), fieldZn, field, "积分流水");
			//准备将Excel的输出流通过response输出到页面下载
			//八进制输出流
			response.setContentType("application/octet-stream");
			response.setCharacterEncoding("UTF-8");
			//这后面可以设置导出Excel的名称，此例中名为student.xls
			response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode("积分流水", "UTF-8") + ".xls");
			//刷新缓冲
			response.flushBuffer();

			//workbook将Excel写入到response的输出流中，供页面下载
			workbook.write(response.getOutputStream());

		} catch (Exception e) {

			log.error(ExceptionUtils.getMessage(e));
			e.printStackTrace();

		}
	}

	/**
	 * 积分结算(相当于客户结算)
	 * | ----> 积分结算 -> 未结算商品 | 此页面是以商品流水的维度去展示的 opt 搜索 下单时间 只能以订单维度 最终
	 * | ----> | ----> 创建结算单 预览
	 * <p>
	 * goodsdetail
	 *
	 * @return
	 */
	@RequestMapping(value = "/createAccountingPreview", method = RequestMethod.POST)
	@ResponseBody
	public R<List<ScoreOrderReconciliationNotYetVo>> createAccountingPreview(

//			String ids
//			@ModelAttribute List<AccountingScoreCustomerCreateSelectedCreditParam> selectCredits
			String selectCredits
	) {

		log.info("createAccountingPreview params {}", selectCredits);

		R<List<ScoreOrderReconciliationNotYetVo>> result = new R<>();

		try {


//			String[] scoreOrderCreditIds = ids.split(",");
//			if (scoreOrderCreditIds.length == 0) {
//				result.setSuccess(false);
//				result.setMessage("请选择至少 1 条流水！");
//				return result;
//			}

			List<AccountingScoreCustomerCreateSelectedCreditParam> credits = JsonUtils.toList(selectCredits, AccountingScoreCustomerCreateSelectedCreditParam.class);

			if (CollectionUtils.isEmpty(credits)) {
				result.setSuccess(false);
				result.setMessage("请选择至少 1 条流水！");
				return result;
			}

			List<String> scoreOrderCreditIds = credits.stream()
					.map(s -> s.getUnifiedOrderCreditId().toString())
					.collect(Collectors.toList());

			Map<String, Object> params = new HashMap<>();
			params.put("ids", scoreOrderCreditIds.toArray());
//			params.put("accountState", Byte.valueOf("2"));

			result = unifiedOrderDubboConsumerService.getScoreOrderReconciliationNotYet(getToken(), params, 0, 99999);

			createAccountingCheck(result);

			if (!result.isSuccess()) {
				return result;
			}

			for (ScoreOrderReconciliationNotYetVo vo : result.getData()) {
				vo.setAccountingStateCustomerName(UnifiedOrderAccountingStateEnum.getDesc(vo.getAccountingStateCustomer()));

				vo.setInvoiceApplyStatusName(UnifiedOrderCreditInvoiceApplyStatusEnum.getDesc(vo.getInvoiceApplyStatus()));
				vo.setInvoiceMakeStatusName(UnifiedOrderCreditInvoiceMakeStatusEnum.getDesc(vo.getInvoiceMakeStatus()));
				vo.setBackStatusName(UnifiedOrderCreditBackStatusEnum.getDesc(vo.getBackStatus()));
			}


//			TODO 处理退货 start
//			List<UnifiedOrderDetail> returnLs = new ArrayList<>();
//			if (returnLs.size() > 0) {
//				for (UnifiedOrderDetail unifiedOrderDetail : returnLs) {
//					ls.add(unifiedOrderDetail);
//				}
//			}
//			TODO 处理退货  end

//			result.setData(data);

		} catch (Exception e) {

			result.setCode(String.valueOf(e.hashCode()));
			result.setSuccess(false);
			result.setMessage("系统查找失败！");

			log.error(ExceptionUtils.getMessage(e));
			e.printStackTrace();

		}

		return result;
	}

	private void createAccountingCheck(R<List<ScoreOrderReconciliationNotYetVo>> result) {

		log.info("createAccountingCheck \n{}", JsonUtils.toJson(result));

		// TODO 检查这些流水是不是同一个
		// 积分类型
		// 积分批次
		// 企业

		// 基准
		ScoreOrderReconciliationNotYetVo benchmark = null;

		for (ScoreOrderReconciliationNotYetVo iterator : result.getData()) {

			if ("wechat".equals(iterator.getBatchs())) {
				continue;
			}

			log.info(JsonUtils.toJson(iterator));

			// 排除 wechat ，当不是 wechat 时 设定基准
			if (null == benchmark) {

				benchmark = iterator;

			} else {

				if (!iterator.getCreditName().equals(benchmark.getCreditName())) {
					result.setSuccess(false);
					result.setMessage("积分类型 不唯一，请重新生成！");
				}

//				if (!iterator.getBatchs().equals(benchmark.getBatchs())) {
//					result.setSuccess(false);
//					result.setMessage("积分批次 不唯一，请重新生成！");
//				}

				if (iterator.getPurchaseVirtId() == null) {
					result.setSuccess(false);
					result.setMessage("企业信息 缺失，请重新生成！");
				}
				if (!iterator.getPurchaseVirtId().equals(benchmark.getPurchaseVirtId())) {
					result.setSuccess(false);
					result.setMessage("企业信息 不唯一，请重新生成！");
				}
			}
		}
	}


	/**
	 * 客户(积分)结算 -> 未对账流水 -> opt创建对账单
	 *
	 * @param accountingScoreCustomerCreateParam
	 * @return
	 * @RequestBody
	 * @ModelAttribute
	 * @Valid
	 */
	@RequestMapping(value = "/createAccounting", method = RequestMethod.POST)
	@ResponseBody
	public R<AccountingScoreCustomer> createAccounting(AccountingScoreCustomerCreateParam accountingScoreCustomerCreateParam) {

		R<AccountingScoreCustomer> result = new R<>();

		try {

			// 订单的 ids
//			String[] ids = accountingScoreCustomerCreateParam.getIds().split(",");
//			if (ids.length == 0) {
//				result.setSuccess(false);
//				result.setMessage("您没有选择要结算的积分流水！");
//				return result;
//			}

//			List<AccountingScoreCustomerCreateSelectedCreditParam> selectCredits = accountingScoreCustomerCreateParam.getSelectCredits();

			List<AccountingScoreCustomerCreateSelectedCreditParam> selectCredits = JsonUtils.toList(accountingScoreCustomerCreateParam.getSelectCredits(), AccountingScoreCustomerCreateSelectedCreditParam.class);

			if (CollectionUtils.isEmpty(selectCredits)) {
				result.setSuccess(false);
				result.setMessage("您没有选择要结算的积分流水！");
				return result;
			}

			List<String> scoreOrderCreditIds = selectCredits.stream()
					.map(s -> s.getUnifiedOrderCreditId().toString())
					.collect(Collectors.toList());

			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

			Date startDate = sdf.parse(accountingScoreCustomerCreateParam.getStartTime());
			Date endDate   = sdf.parse(accountingScoreCustomerCreateParam.getEndTime());


			// 取出选中的 积分流水
			Map<String, Object> queryMap = new HashMap<>();
			queryMap.put("ids", scoreOrderCreditIds.toArray());
			R<List<ScoreOrderReconciliationNotYetVo>> resultCredit = unifiedOrderDubboConsumerService.getScoreOrderReconciliationNotYet(getToken(), queryMap, 0, 99999);

			createAccountingCheck(resultCredit);

			if (!resultCredit.isSuccess()) {
				result.setSuccess(false);
				result.setMessage(resultCredit.getMessage());
				return result;
			}

			// 统计结算单 积分总额
			BigDecimal dzMoney = resultCredit.getData().stream().map(a -> a.getBalance()).reduce(BigDecimal.ZERO, BigDecimal::add);
			accountingScoreCustomerCreateParam.setAccountingAmount(dzMoney);

			AccountingScoreCustomer dzMain = accountingScoreCustomerDubboConsumerService.createScoreAccountingCustomer(getToken(), resultCredit.getData(), accountingScoreCustomerCreateParam);

			if (dzMain.getId() > 0) {

				result.setSuccess(true);
				result.setData(dzMain);

				Map<String, Object> headMap = new HashMap<>();

				headMap.put("encrypt_id", MyTools.encode(dzMain.getId().toString()));

				result.setHeadData(headMap);

			} else {

				result.setSuccess(false);
				result.setMessage("创建 结算单 失败！");

			}

		} catch (Exception e) {

			result.setSuccess(false);
			result.setMessage("系统错误，请联系管理员！");

			log.error(ExceptionUtils.getMessage(e));
			e.printStackTrace();
		}

		return result;
	}


}
