package org.springblade.flow.mall.service.impl;

import cn.hutool.core.convert.Convert;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.common.cache.FlowCache;
import org.springblade.common.enums.AppConstant;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.tool.support.Kv;
import org.springblade.core.tool.utils.Func;
import org.springblade.flow.business.constant.AuditCandidate;
import org.springblade.flow.business.service.IFlowService;
import org.springblade.flow.core.constant.ProcessConstant;
import org.springblade.flow.core.entity.BladeFlow;
import org.springblade.flow.core.utils.FlowUtil;
import org.springblade.flow.core.utils.TaskUtil;
import org.springblade.flow.mall.entity.MallInvitationCallbackVO;
import org.springblade.flow.mall.service.IAuditMallService;
import org.springblade.flow.mall.task.MallInvitationTask;
import org.springblade.flow.mall.task.callback.MallInvitationCallback;
import org.springblade.flow.mall.task.callback.MallInvitationFailCallback;
import org.springblade.flow.mall.task.callback.MallInvitationSignCallback;
import org.springblade.flow.mall.task.callback.MallInvitationSuccessCallback;
import org.springblade.flow.shop.entity.InvitationCallbackData;
import org.springblade.flow.shop.entity.ProcessAudit;
import org.springblade.flow.shop.entity.ShopEnum;
import org.springblade.ldt.mall.entity.Mall;
import org.springblade.ldt.mall.service.IMallService;
import org.springblade.ldt.shop.entity.Audit;
import org.springblade.ldt.shop.service.IAuditService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

/**
 * @author July
 * @version 1.0.0
 * @ClassName AuditMallService.java
 * @Description 商场入驻审核服务实现类
 * @createTime 2021年09月22日 11:22:00
 */
@Service
@Slf4j
@AllArgsConstructor
public class AuditMallService implements IAuditMallService {

	private final IFlowService flowService;
	private final IMallService mallService;
	private final IAuditService auditService;
	private final MallInvitationSuccessCallback mallInvitationSuccessCallback;
	private final MallInvitationFailCallback mallInvitationFailCallback;
	private final MallInvitationSignCallback mallInvitationSignCallback;



	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean startProcess(ProcessAudit processAudit) {
		Audit audit = processAudit.getAudit();
		Mall mall = mallService.getById(audit.getEntityId());
		audit.setType(AppConstant.PLATFORM.MALL.name());
		audit.setShopLogo(mall.getLogo());
		audit.setShopName(mall.getMallName());
		audit.setShortName(mall.getMallName());

		String businessTable = FlowUtil.getBusinessTable(ProcessConstant.AUDIT_MALL);
		if (Func.isEmpty(processAudit.getId())) {

			audit.setAuditStatus(ShopEnum.WAITING_INVITATION.name());
			mall.setAuditStatus(ShopEnum.WAITING_INVITATION.name());

			auditService.save(audit);

			// 启动流程
			Kv variables = Kv.create()
				.set("audit", audit)
				.set("mallId", audit.getEntityId())
				.set("yeepay",AuditCandidate.YEEPAY_PLATFORM.name());

			MallInvitationTask.apply(audit);

			BladeFlow flow = flowService.startProcessInstanceById(
				audit.getProcessDefinitionId(),
				FlowUtil.getBusinessKey(businessTable,
					String.valueOf(audit.getId())), variables,
				TaskUtil.getTaskUserForApp(Convert.toStr(audit.getEntityId()), TaskUtil.APP_MALL));

			if (Func.isNotEmpty(flow)) {
				log.debug("流程已启动,流程ID:" + flow.getProcessInstanceId());
				// 返回流程id写入
				audit.setProcessInstanceId(flow.getProcessInstanceId());
				auditService.updateById(audit);
				mallService.updateById(mall);

				//缓存入驻申请的数据，方便后续回调使用
				FlowCache.putMallAudit(MallInvitationCallbackVO.builder()
						.audit(audit)
						.mall(mall)
						.variables(flow.getVariables())
						.build(),
					audit.getRequestNo());
			} else {
				throw new ServiceException("开启流程失败");
			}
		} else {
			auditService.updateById(audit);
			mallService.updateById(mall);
		}
		return true;
	}

	@Override
	public void invitationCallback(InvitationCallbackData invitationCallbackData) {
		InvitationCallbackData.applicationStatusType applicationStatusType = InvitationCallbackData.applicationStatusType.valueOf(invitationCallbackData.getApplicationStatus());
		switch (applicationStatusType) {
			case AGREEMENT_SIGNING:
				mallInvitationSignCallback.handle(invitationCallbackData);
				break;
			case REVIEW_BACK:
				mallInvitationFailCallback.handle(invitationCallbackData);
				break;
			case COMPLETED:
				mallInvitationSuccessCallback.handle(invitationCallbackData);
				break;
			default:
				break;
		}
	}
}
