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

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.superdesk.uniorder.common.enums.invoice.InvoiceInvoicedIsOverdueEnum;
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.organisation.SysEnterpriseExtAccounting;
import cn.superdesk.uniorder.dto.vo.invoice.customer.invoiced.InvoiceInvoicedExcelExportVo;
import cn.superdesk.uniorder.pattern.state.invoice.customer.invoiceInvoiced.isOverdue.context.InvoiceInvoicedFieldIsOverdueContext;
import cn.superdesk.uniorder.service.invoice.customer.invoiced.InvoiceInvoicedFieldIsOverdueService;
import cn.superdesk.uniorder.service.invoice.customer.invoiced.InvoiceInvoicedOperationLogService;
import cn.superdesk.uniorder.service.invoice.customer.invoiced.InvoiceInvoicedService;
import cn.superdesk.uniorder.service.organisation.SysEnterpriseExtAccountingService;
import cn.superdesk.uniorder.common.numerical.AnIntegerUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

/**
 * @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 InvoiceInvoicedFieldIsOverdueServiceImpl implements InvoiceInvoicedFieldIsOverdueService {

	@Autowired
	private InvoiceInvoicedService invoiceInvoicedService;

	@Autowired
	private InvoiceInvoicedOperationLogService invoiceInvoicedOperationLogService;

	@Autowired
	private SysEnterpriseExtAccountingService sysEnterpriseExtAccountingService;

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

	// 状态流转为 正常(0, "正常")
	public void opInitOrResetByStateMachine(InvoiceInvoiced entity, InvoiceInvoicedExcelExportVo taskParams, LoginSysUser loginSysUser) {

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

		// TODO 更新状态逻辑...

		forUpdate.setIsOverdue(InvoiceInvoicedIsOverdueEnum.正常.getKey());

		invoiceInvoicedService.updateInvoiceInvoicedByPrimaryKeySelective(forUpdate);
	}

	// 状态流转为 逾期(1, "逾期")
	public void opOverduedByStateMachine(InvoiceInvoiced entity, InvoiceInvoicedExcelExportVo form, LoginSysUser loginSysUser) {

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

		if (null == form.getReceivableAmount()) {
			form.setReceivableAmount(form.getTotalAmountIncludingTax());
			forUpdate.setReceivableAmount(form.getTotalAmountIncludingTax());
		}

		if (null == form.getBackCollectionAmountAlready()) {
			form.setBackCollectionAmountAlready(BigDecimal.ZERO);
			forUpdate.setBackCollectionAmountAlready(BigDecimal.ZERO);
		}

		if (null == form.getBackCollectionAmountWaitFor()) {
			form.setBackCollectionAmountWaitFor(BigDecimal.ZERO);
			forUpdate.setBackCollectionAmountWaitFor(BigDecimal.ZERO);
		}

//		【后端部分完成-20210811-更新-已整理-20210727-应收账款,逾期天数定时任务。需求外 附加功能 操作日志】 https://www.tapd.cn/33003868/prong/stories/view/1133003868001002627
//		④该项目企业的企业账期:
//		A、取该发票所属的项目企业,项目企业的企业账期来源于"统一订单后台-系统管理-企业管理"企业账期设置的回款天数;---- 待处理
//		B、若该发票未挂靠项目企业或项目企业的企业账期为空,即默认为"0";---- 待处理

		// 产品说默认为0,喜欢就好
		Integer diff = 0;
		if (null != form.getOutVirtId()) {
			SysEnterpriseExtAccounting sysEnterpriseExtAccounting = sysEnterpriseExtAccountingService.findSysEnterpriseExtAccountingByOutVirtIdWithIn(form.getOutVirtId());
			diff = sysEnterpriseExtAccounting.getAccountPeriod();
		}

		// TODO 更新状态逻辑...
		// 简单判定
		// 实际应收金额 != 已回款金额
		if (form.getBackCollectionAmountAlready().compareTo(form.getReceivableAmount()) < 0) {

			forUpdate.setIsOverdue(InvoiceInvoicedIsOverdueEnum.逾期.getKey());

			Long    betweenDay  = DateUtil.between(DateUtil.date(), form.getInvoicedDate(), DateUnit.DAY);
			Integer overdueDays = AnIntegerUtils.getInteger(betweenDay)-diff;
			forUpdate.setOverdueDays(overdueDays);

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

			invoiceInvoicedService.updateInvoiceInvoicedByPrimaryKeySelective(forUpdate);

			// 操作日志
			invoiceInvoicedOperationLogService.commonOperationLog(entity, forUpdate, form, loginSysUser, InvoiceInvoicedOperationLogOperationTypeEnum.逾期检查);


		}

//		forUpdate.setIsOverdue(InvoiceInvoicedIsOverdueEnum.逾期.getKey());
//		invoiceInvoicedService.updateInvoiceInvoicedByPrimaryKeySelective(forUpdate);
	}

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


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

	// 状态流转为 正常(0, "正常")
	public void opInitOrReset(InvoiceInvoicedExcelExportVo form, LoginSysUser loginSysUser) {

		InvoiceInvoiced entity = invoiceInvoicedService.findInvoiceInvoicedById(form.getId());

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

	// 状态流转为 逾期(1, "逾期")
	public void opOverdued(InvoiceInvoicedExcelExportVo form, LoginSysUser loginSysUser) {

		InvoiceInvoiced entity = invoiceInvoicedService.findInvoiceInvoicedById(form.getId());

		InvoiceInvoicedFieldIsOverdueContext context = new InvoiceInvoicedFieldIsOverdueContext(entity, form, loginSysUser);
		context.opOverdued();
	}

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

	/**
	 * 处理判定
	 *
	 * @param taskParams
	 * @param loginSysUser
	 */
	public void processInvoiceInvoicedsOverdueTask(InvoiceInvoicedExcelExportVo taskParams, LoginSysUser loginSysUser) {

		log.info("{}", AnJsonUtils.toJson(taskParams));

		// 逾期检查
		opOverdued(taskParams, loginSysUser);


	}
}
