package org.security.trans.common.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import org.apache.commons.lang.StringUtils;
import org.security.flow.core.constant.ProcessConstant;
import org.security.flow.core.feign.IFlowClient;
import org.security.ht.entity.common.FlowEntity;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public interface FlowableService<T extends FlowEntity> extends IService<T> {
	/**
	 * 删除流程（保留流程历史等信息）
	 *
	 * @param processInstanceId 流程id
	 * @throws ServiceException 根据流程id没有查询到流程实例
	 */
	default Boolean deleteProcessInstanceOnly(String processInstanceId) {
		return false;
	}

	/**
	 * 删除实体及流程（包括历史记录等信息）
	 *
	 * @param ids 实体id列表
	 * @throws ServiceException 根据流程id没有查询到流程实例
	 */
	@Transactional
	default Boolean deleteWithFlowByIds(String ids, IFlowClient flowClient) {
		List<Long> idList = Func.toLongList(ids);
		if (CollectionUtils.isEmpty(idList)) {
			return false;
		}
		LambdaQueryWrapper<T> wrapper = new LambdaQueryWrapper<>();
		wrapper
			.setEntityClass((Class<T>) getEntityClass())
			.select(T::getProcessInstanceId)
			.in(T::getId, idList);
		List<T> list = this.list(wrapper);
		List<String> instanceIds = list.stream().map(T::getProcessInstanceId).collect(Collectors.toList());
		boolean deleteEntityResult = SqlHelper.retBool(getBaseMapper().deleteBatchIds(idList));
		if (!deleteEntityResult) {
			return false;
		}
		R deleteFlowResult = flowClient.deleteProcessInstanceByInstanceId(StringUtils.join(instanceIds, ","));
		if (!deleteFlowResult.isSuccess()) {
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			return false;
		}
		return true;
	}

	/**
	 * 只删除流程（包括历史记录等信息）
	 *
	 * @param ids 实体id列表
	 * @throws ServiceException 根据流程id没有查询到流程实例
	 */
	@Transactional
	default Boolean deleteFlowOnly(String ids, IFlowClient flowClient) {
		List<Long> idList = Func.toLongList(ids);
		if (CollectionUtils.isEmpty(idList)) {
			return false;
		}
		LambdaQueryWrapper<T> wrapper = new LambdaQueryWrapper<>();
		wrapper
			.setEntityClass((Class<T>) getEntityClass())
			.select(T::getProcessInstanceId)
			.in(T::getId, idList);
		List<T> list = this.list(wrapper);
		List<String> instanceIds = list.stream().map(T::getProcessInstanceId).collect(Collectors.toList());
		R deleteFlowResult = flowClient.deleteProcessInstanceByInstanceId(StringUtils.join(instanceIds, ","));
		if (!deleteFlowResult.isSuccess()) {
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			return false;
		}
		return true;
	}

	default Boolean updateStateById(String id, String state) {
		LambdaUpdateWrapper<T> wrapper = new LambdaUpdateWrapper<>();
		wrapper
			.setEntityClass((Class<T>) getEntityClass())
			.eq(T::getId, id)
			.set(T::getState, state);
		return this.update(wrapper);
	}

	default R afterFlowFinished(String id, Boolean pass, Map<String, Object> variables) {
		String state;
		if (null == pass) {
			state = ProcessConstant.CANCEL_STATE;
		} else if (pass) {
			state = ProcessConstant.PASS_STATE;
		} else {
			state = ProcessConstant.REJECT_STATE;
		}
		return R.status(this.updateStateById(id, state));
	}
}
