package cn.superdesk.uniorder.service.invoice.customer.invoiced.impl;

import cn.hutool.core.date.DateUtil;
import cn.superdesk.uniorder.common.enums.invoice.customer.InvoiceApplyCustomerBackAccountStatusEnum;
import cn.superdesk.uniorder.common.enums.invoice.InvoiceInvoicedOperationLogOperationTypeEnum;
import cn.superdesk.uniorder.common.json.AnJsonUtils;
import cn.superdesk.uniorder.common.security.dto.LoginSysUser;
import cn.superdesk.uniorder.dao.entity.invoice.customer.invoiced.InvoiceInvoiced;
import cn.superdesk.uniorder.dao.entity.invoice.customer.invoiced.InvoiceInvoicedBackCollectionOperationLog;
import cn.superdesk.uniorder.dao.entity.operation.ExcelImportLog;
import cn.superdesk.uniorder.dto.param.invoice.excel.InvoiceInvoicedOpBackCollectionForm;
import cn.superdesk.uniorder.pattern.state.invoice.customer.invoiceInvoiced.isBackCollection.context.InvoiceInvoicedFieldIsBackCollectionContext;
import cn.superdesk.uniorder.service.invoice.customer.invoiced.InvoiceInvoicedBackCollectionOperationLogService;
import cn.superdesk.uniorder.service.invoice.customer.invoiced.InvoiceInvoicedFieldIsBackCollectionService;
import cn.superdesk.uniorder.service.invoice.customer.invoiced.InvoiceInvoicedOperationLogService;
import cn.superdesk.uniorder.service.invoice.customer.invoiced.InvoiceInvoicedService;
import cn.superdesk.uniorder.service.operation.ExcelImportLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;

/**
 * @Description: 简易状态机 星型结构
 * @Author: linjinyu
 * @CreateDate: 10/12/20 4:28 PM
 * @UpdateUser: linjinyu
 * @UpdateDate: 10/12/20 4:28 PM
 * @UpdateRemark: 修改内容
 * @Version: 1.0
 */
@Slf4j
@Service
public class InvoiceInvoicedFieldIsBackCollectionServiceImpl implements InvoiceInvoicedFieldIsBackCollectionService {

	@Autowired
	private InvoiceInvoicedService invoiceInvoicedService;

	@Autowired
	private InvoiceInvoicedOperationLogService               invoiceInvoicedOperationLogService;
	@Autowired
	private InvoiceInvoicedBackCollectionOperationLogService invoiceInvoicedBackCollectionOperationLogService;

	@Autowired
	private ExcelImportLogService excelImportLogService;

	/****************************************** 状态机 公共方法 机内使用 实际流转 重用 start ******************************************/

	/**
	 * 回款日志
	 *
	 * @param entity
	 * @param form
	 * @param loginSysUser
	 */
	private void commonBackCollectionOperationLog(InvoiceInvoiced entity, InvoiceInvoicedOpBackCollectionForm form, LoginSysUser loginSysUser) {

		// 回款日志
		InvoiceInvoicedBackCollectionOperationLog invoiceInvoicedBackCollectionOperationLog = new InvoiceInvoicedBackCollectionOperationLog();

		/****************************************** 唯一标识的 start ******************************************/
		invoiceInvoicedBackCollectionOperationLog.setBatchId(form.getBatchId());
		invoiceInvoicedBackCollectionOperationLog.setInvoiceInvoicedId(form.getId());
		invoiceInvoicedBackCollectionOperationLog.setInvoiceNumber(form.getInvoiceNumber());

		/****************************************** 目前没有用 start ******************************************/
		invoiceInvoicedBackCollectionOperationLog.setTotalAmount(entity.getTotalAmount());
		invoiceInvoicedBackCollectionOperationLog.setTaxRate(entity.getTaxRate());
		invoiceInvoicedBackCollectionOperationLog.setTotalTax(entity.getTotalTax());

		/****************************************** 原本记录的 start ******************************************/
		invoiceInvoicedBackCollectionOperationLog.setTotalAmountIncludingTax(entity.getTotalAmountIncludingTax());
		invoiceInvoicedBackCollectionOperationLog.setReceivableAmount(entity.getReceivableAmount());
		invoiceInvoicedBackCollectionOperationLog.setBackCollectionAmountAlready(entity.getBackCollectionAmountAlready());
		invoiceInvoicedBackCollectionOperationLog.setBackCollectionAmountWaitFor(entity.getBackCollectionAmountWaitFor());

		/****************************************** 本次操作的 start ******************************************/
		invoiceInvoicedBackCollectionOperationLog.setCreateTime(DateUtil.date());
		invoiceInvoicedBackCollectionOperationLog.setCreateUserId(loginSysUser.getSysUserId());
		invoiceInvoicedBackCollectionOperationLog.setCreateUserName(loginSysUser.getSysUserName());

		invoiceInvoicedBackCollectionOperationLog.setBackCollectionTime(form.getBackCollectionTime());
		invoiceInvoicedBackCollectionOperationLog.setBackCollectionAmount(form.getBackCollectionAmount());

		invoiceInvoicedBackCollectionOperationLogService.addInvoiceInvoicedBackCollectionOperationLog(invoiceInvoicedBackCollectionOperationLog);

	}

	/**
	 * 回款处理
	 *
	 * @param entity
	 * @param form
	 * @param loginSysUser
	 * @return
	 */
	private InvoiceInvoiced commonBackCollectionOperationProcess(InvoiceInvoiced entity, InvoiceInvoicedOpBackCollectionForm form, LoginSysUser loginSysUser) {

		InvoiceInvoiced forUpdate = new InvoiceInvoiced();
		forUpdate.setId(entity.getId());


		// TODO 更新状态逻辑...
		if (null != entity.getBackCollectionAmountWaitFor() && entity.getBackCollectionAmountWaitFor().compareTo(BigDecimal.ZERO) > 0) {

			if (entity.getBackCollectionAmountWaitFor().compareTo(form.getBackCollectionAmount()) == 0) {
				forUpdate.setIsBackCollection(InvoiceApplyCustomerBackAccountStatusEnum.已回款.getKey());
			}

			if (entity.getBackCollectionAmountWaitFor().compareTo(form.getBackCollectionAmount()) < 0) {

				forUpdate.setIsBackCollection(InvoiceApplyCustomerBackAccountStatusEnum.部分回款.getKey());
			}

			// TODO 这个可能出现吗?
			if (entity.getBackCollectionAmountWaitFor().compareTo(form.getBackCollectionAmount()) > 0) {

				forUpdate.setIsBackCollection(InvoiceApplyCustomerBackAccountStatusEnum.已回款.getKey());
			}

			if (null == entity.getBackCollectionAmountAlready()) {
				entity.setBackCollectionAmountAlready(BigDecimal.ZERO);
			}
			if (null == entity.getBackCollectionAmountWaitFor()) {
				entity.setBackCollectionAmountWaitFor(BigDecimal.ZERO);
			}

			forUpdate.setBackCollectionAmountAlready(entity.getBackCollectionAmountAlready().add(form.getBackCollectionAmount()));
			forUpdate.setBackCollectionAmountWaitFor(entity.getBackCollectionAmountWaitFor().subtract(form.getBackCollectionAmount()));
			forUpdate.setBackCollectionTime(form.getBackCollectionTime());

			forUpdate.setPersonNameCashier(loginSysUser.getSysUserName());
			forUpdate.setSysUserIdCashier(loginSysUser.getSysUserId());

			forUpdate.setUpdateTime(DateUtil.date());
			forUpdate.setUpdateUserId(loginSysUser.getSysUserId());
			forUpdate.setUpdateUserName(loginSysUser.getFullName());
		}


		invoiceInvoicedService.updateInvoiceInvoicedByPrimaryKeySelective(forUpdate);

		return forUpdate;
	}


	// 状态流转为 未回款(0, "未回款")
	public void opInitOrResetByStateMachine(InvoiceInvoiced entity, InvoiceInvoicedOpBackCollectionForm form, LoginSysUser loginSysUser) {

		InvoiceInvoiced forUpdate = new InvoiceInvoiced();
		forUpdate.setId(entity.getId());

		// TODO 更新状态逻辑...
		forUpdate.setUpdateTime(DateUtil.date());
		forUpdate.setUpdateUserId(loginSysUser.getSysUserId());
		forUpdate.setUpdateUserName(loginSysUser.getFullName());

		forUpdate.setIsBackCollection(InvoiceApplyCustomerBackAccountStatusEnum.未回款.getKey());

		invoiceInvoicedService.updateInvoiceInvoicedByPrimaryKeySelective(forUpdate);
	}

	// 状态流转为 部分回款(1, "部分回款")
	public void opPartByStateMachine(InvoiceInvoiced entity, InvoiceInvoicedOpBackCollectionForm form, LoginSysUser loginSysUser) {

		log.info("InvoiceInvoicedFieldIsBackCollectionServiceImpl -> opPartByStateMachine params:\n{}\n{}\n{}", AnJsonUtils.toJson(entity), AnJsonUtils.toJson(form), AnJsonUtils.toJson(loginSysUser));

		// 回款日志
		commonBackCollectionOperationLog(entity, form, loginSysUser);

		// 更新该更新的
		InvoiceInvoiced forUpdate = commonBackCollectionOperationProcess(entity, form, loginSysUser);

		// 操作日志
		invoiceInvoicedOperationLogService.commonOperationLog(entity, forUpdate, form, loginSysUser, InvoiceInvoicedOperationLogOperationTypeEnum.回款操作_部分回款);

	}

	// 状态流转为 全部回款(2, "全部回款")
	public void opCompleteByStateMachine(InvoiceInvoiced entity, InvoiceInvoicedOpBackCollectionForm form, LoginSysUser loginSysUser) {

//		InvoiceInvoiced forUpdate = new InvoiceInvoiced();
//		forUpdate.setId(entity.getId());
//
//		// TODO 更新状态逻辑...
//
//		forUpdate.setIsBackCollection(InvoiceApplyBackAccountStatusEnum.已回款.getKey());
//
//		invoiceInvoicedService.updateInvoiceInvoicedByPrimaryKeySelective(forUpdate);

		opPartByStateMachine(entity, form, loginSysUser);
	}

	// 状态流转为 红冲发票(69, "红冲发票")
	public void opRedWriteOffByStateMachine(InvoiceInvoiced entity, InvoiceInvoicedOpBackCollectionForm form, LoginSysUser loginSysUser) {

		InvoiceInvoiced forUpdate = new InvoiceInvoiced();
		forUpdate.setId(entity.getId());

		// TODO 更新状态逻辑...
		forUpdate.setUpdateTime(DateUtil.date());
		forUpdate.setUpdateUserId(loginSysUser.getSysUserId());
		forUpdate.setUpdateUserName(loginSysUser.getFullName());

		forUpdate.setIsBackCollection(InvoiceApplyCustomerBackAccountStatusEnum.发票红冲.getKey());

		invoiceInvoicedService.updateInvoiceInvoicedByPrimaryKeySelective(forUpdate);
	}

	/****************************************** 状态机 公共方法 机内使用 实际流转 重用   end ******************************************/


	/****************************************** 状态机 外部使用 类门面 start ******************************************/

	private InvoiceInvoiced findByOpBackCollectionForm(InvoiceInvoicedOpBackCollectionForm form) {

		InvoiceInvoiced entity = null;

		if (null != form.getId()) {

			entity = invoiceInvoicedService.findInvoiceInvoicedById(form.getId());
			form.setInvoiceNumber(entity.getInvoiceNumber());

		} else if (null != form.getInvoiceNumber()) {
			entity = invoiceInvoicedService.findInvoiceInvoicedByInvoiceNumber(form.getInvoiceNumber());
			form.setId(entity.getId());
		}

		return entity;
	}


	// 状态流转为 未回款(0, "未回款")
	public void opInitOrReset(InvoiceInvoicedOpBackCollectionForm form, LoginSysUser loginSysUser) {

		InvoiceInvoiced entity = findByOpBackCollectionForm(form);
		if (null == entity) {
//			记录问题
			return;
		}

		InvoiceInvoicedFieldIsBackCollectionContext context = new InvoiceInvoicedFieldIsBackCollectionContext(entity, form, loginSysUser);
		context.opInitOrReset();
	}

	// 状态流转为 部分回款(1, "部分回款")
	public void opPart(InvoiceInvoicedOpBackCollectionForm form, LoginSysUser loginSysUser) {

		log.info("opPart params(InvoiceInvoicedOpBackCollectionForm form, LoginSysUser loginSysUser) \n{}\n{}", AnJsonUtils.toJson(form), AnJsonUtils.toJson(loginSysUser));

		InvoiceInvoiced entity = findByOpBackCollectionForm(form);
		if (null == entity) {
//			记录问题
			return;
		}

		InvoiceInvoicedFieldIsBackCollectionContext context = new InvoiceInvoicedFieldIsBackCollectionContext(entity, form, loginSysUser);
		context.opPart();
	}

	public void opPartBatchByImportExcel(List<InvoiceInvoicedOpBackCollectionForm> formList, LoginSysUser loginSysUser) {

//		log.info("opPartBatchByImportExcel params(List<InvoiceInvoicedOpBackCollectionForm> formList, LoginSysUser loginSysUser) \n{}\n{}", JsonUtils.toJson(formList), JsonUtils.toJson(loginSysUser));

		// 现在这个如果有问题 怎样返回呢 还是走异步吧? websocket?

		formList.forEach(form -> {
			opPart(form, loginSysUser);
		});
	}

	// 状态流转为 全部回款-已回款(2, "全部回款-已回款")
	public void opComplete(InvoiceInvoicedOpBackCollectionForm form, LoginSysUser loginSysUser) {

		InvoiceInvoiced entity = findByOpBackCollectionForm(form);
		if (null == entity) {
//			记录问题
			return;
		}

		InvoiceInvoicedFieldIsBackCollectionContext context = new InvoiceInvoicedFieldIsBackCollectionContext(entity, form, loginSysUser);
		context.opComplete();
	}

	// 状态流转为 红冲发票(69, "红冲发票")
	public void opRedWriteOff(InvoiceInvoicedOpBackCollectionForm form, LoginSysUser loginSysUser) {

		InvoiceInvoiced entity = findByOpBackCollectionForm(form);
		if (null == entity) {
//			记录问题
			return;
		}

		InvoiceInvoicedFieldIsBackCollectionContext context = new InvoiceInvoicedFieldIsBackCollectionContext(entity, form, loginSysUser);
		context.opRedWriteOff();
	}

	/****************************************** 状态机 外部使用 类门面   end ******************************************/


	public void opPartBatchByExcelImportLogStep01(List<InvoiceInvoicedOpBackCollectionForm> formList, LoginSysUser loginSysUser) {


		formList.forEach(row -> {

//			row.get

			ExcelImportLog entity = new ExcelImportLog();
			entity.setBatchId(row.getBatchId());
			entity.setOperationType(InvoiceInvoicedOpBackCollectionForm.class.getName());
			entity.setCreateTime(DateUtil.date());
			entity.setCreateUserId(loginSysUser.getSysUserId());
			entity.setCreateUserName(loginSysUser.getSysUserName());

			entity.setRowData(AnJsonUtils.toJson(row));

//			entity.setProcessResult();
//			entity.setProcessReport();

		});

//		excelImportLogService.addExcelImportLog();

	}
}
