package com.mortals.xhx.module.api.handler.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mortals.framework.common.code.YesNo;
import com.mortals.framework.exception.AppException;
import com.mortals.xhx.common.code.AssetFlowStatusEnum;
import com.mortals.xhx.module.api.handler.AssetFlowEventHandler;
import com.mortals.xhx.module.api.model.AssetEventLog;
import com.mortals.xhx.module.asset.dao.AssetDao;
import com.mortals.xhx.module.asset.model.*;
import com.mortals.xhx.module.asset.service.AssetFlowEventFieldService;
import com.mortals.xhx.module.asset.service.AssetFlowEventLogService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;

import java.util.Date;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 抽象事件处理器
 *
 * @author luoshichao
 * @Description
 * @date 2021/1/8 14:46
 */
public abstract class AbstractAssetFlowEventHandler implements AssetFlowEventHandler {
	protected Log log = LogFactory.getLog(this.getClass());
	@Autowired
	private AssetFlowEventLogService assetFlowEventLogService;
	/*@Autowired
	private AssetService assetService;*/
	@Autowired
	private AssetFlowEventFieldService assetFlowEventFieldService;

	@Autowired
	private AssetDao assetDao;

	/**
	 * 具体事件个性化业务处理(子类实现)
	 * 
	 * @param assetEntity
	 * @param eventEntity
	 * @param req
	 */
	public abstract void handle(AssetEntity assetEntity, AssetFlowEventEntity eventEntity, AssetEventLog req);

	@Override
	public final void execute(AssetEntity assetEntity, AssetFlowEventEntity eventEntity, AssetEventLog req) {
		// 参数校验
		this.validateParam(assetEntity, eventEntity, req);
		// 各具体事件个性化业务处理
		this.handle(assetEntity, eventEntity, req);
		// 更新资产状态
		AssetEntity asset = this.updateAssetFlowStatus(assetEntity, eventEntity, req);
		// 保存资产事件日志
		this.saveEventLog(asset, eventEntity, req);

	}

	/**
	 * 记录事件日志
	 * 
	 * @param eventEntity  事件
	 * @param req          参数
	 */
	private void saveEventLog(AssetEntity assetEntity, AssetFlowEventEntity eventEntity, AssetEventLog req) {
		AssetFlowEventLogEntity assetFlowEventLogEntity = new AssetFlowEventLogEntity();
		assetFlowEventLogEntity.setEventCode(eventEntity.getCode());
		assetFlowEventLogEntity.setAssetNum(assetEntity.getAssetNum());
		assetFlowEventLogEntity.setBeforeStatus(assetEntity.getBeforeFlowStatus());
		assetFlowEventLogEntity.setAfteStatus(assetEntity.getFlowStatus());
		assetFlowEventLogEntity.setEventStartTime(req.getEventStartTime() != null ? req.getEventStartTime() : new Date());
		assetFlowEventLogEntity.setEventTime(req.getEventTime() != null ? req.getEventTime() : new Date());
		assetFlowEventLogEntity.setEventUser(req.getEventUser());
		assetFlowEventLogEntity.setEventAfterUser(req.getEventAfterUser());
		assetFlowEventLogEntity.setEventAddress(req.getEventAddress());
		assetFlowEventLogEntity.setEventImgUrl(req.getEventImgUrl());
		if(req.getEventExtInfo() != null){
			assetFlowEventLogEntity.setEventExtInfo(JSON.toJSONString(req.getEventExtInfo()));
		}
		assetFlowEventLogEntity.setRemark(req.getRemark());
		assetFlowEventLogEntity.setCreateTime(new Date());
		assetFlowEventLogEntity.setShowInfo(req.getShowInfo());
		assetFlowEventLogService.save(assetFlowEventLogEntity, null);
	}

	/**
	 * 更新资产信息
	 * 
	 * @param assetEntity 资产
	 * @param eventEntity 事件
	 * @param req         参数
	 */
	private AssetEntity updateAssetFlowStatus(AssetEntity assetEntity, AssetFlowEventEntity eventEntity,
			AssetEventLog req) {

		AssetEntity updateAsset = new AssetEntity();
		updateAsset.setAssetNum(assetEntity.getAssetNum());
		updateAsset.setId(assetEntity.getId());
		updateAsset.setUpdateTime(new Date());
		updateAsset.setUpdateUser(req.getEventUser());
		if (AssetFlowStatusEnum.Special_598.getValue().equals(eventEntity.getAfterFlowStatus() + "") ) {// 回前状态
			int beforeFlowStatus = assetEntity.getFlowStatus();
			updateAsset.setFlowStatus(assetEntity.getBeforeFlowStatus());
			updateAsset.setBeforeFlowStatus(beforeFlowStatus);
			assetDao.update(updateAsset);
		} else if (AssetFlowStatusEnum.Special_599.getValue().equals(eventEntity.getAfterFlowStatus() + "") ) {// 不变状态,不用保存到数据库
			updateAsset.setFlowStatus(assetEntity.getFlowStatus());
			updateAsset.setBeforeFlowStatus(assetEntity.getFlowStatus());
		} else {
			int beforeFlowStatus = assetEntity.getFlowStatus();
			updateAsset.setFlowStatus(eventEntity.getAfterFlowStatus());
			updateAsset.setBeforeFlowStatus(beforeFlowStatus);
			assetDao.update(updateAsset);
		}
		return updateAsset;
	}

	/**
	 * 根据事件编码获取扩展字段配置
	 * 
	 * @param eventCode
	 * @return
	 */
	protected Map<String, AssetFlowEventFieldEntity> getEventFieldList(String eventCode) {
		AssetFlowEventFieldQuery query = new AssetFlowEventFieldQuery();
		query.setEventCode(eventCode);
		query.setEnabled(YesNo.YES.getValue());
		Map<String, AssetFlowEventFieldEntity> map = assetFlowEventFieldService.find(query, null).stream()
				.collect(Collectors.toMap(AssetFlowEventFieldEntity::getFieldCode, Function.identity()));
		return map;
	}

	/**
	 * 校验参数(包括:扩展参数)
	 * 
	 * @param req
	 */
	@Override
	public void validateParam(AssetEntity assetEntity, AssetFlowEventEntity eventEntity, AssetEventLog req) {
		if (!eventEntity.getBeforeFlowStatus().contains(AssetFlowStatusEnum.Special_597.getValue()) && !eventEntity.getBeforeFlowStatus().contains("" + assetEntity.getFlowStatus())) {
			throw new AppException("资产状态已变更，不能进行当前操作");
		}

		try {
			Assert.notEmpty(req.getAssetNumList(), "资产码参数不为空");
			Assert.notNull(req.getEventCode(), "事件码参数不为空");
			Assert.notNull(req.getEventUser(), "经手人参数不为空");
			Assert.notNull(req.getEventAfterUser(), "事件关联人参数不为空");
			Assert.notNull(req.getEventAddress(), "事件发生地参数不为空");
			Assert.notNull(req.getEventImgUrl(), "事件关联图像参数不为空");
			//Assert.notNull(req.getEventTime(), "事件发生时间参数不为空");
			// 检验扩展字段
			validateExtField(assetEntity, eventEntity, req);
		} catch (IllegalArgumentException e) {
			throw new AppException(e.getMessage());
		}
	}

	/**
	 * 检验扩展字段
	 * 
	 * @param assetEntity
	 * @param eventEntity
	 * @param req
	 */
	protected void validateExtField(AssetEntity assetEntity, AssetFlowEventEntity eventEntity, AssetEventLog req) {
		Map<String, AssetFlowEventFieldEntity> cnfMap = getEventFieldList(req.getEventCode().toString());
		JSONObject reqMap = new JSONObject();
		try {
			reqMap = new JSONObject(req.getEventExtInfo());
		} catch (Exception e) {
			log.debug("EventExtInfo error", e);
		}
		for (AssetFlowEventFieldEntity extField : cnfMap.values()) {
			Object val = reqMap.get(extField.getFieldCode());
			if (YesNo.NO.getValue() == extField.getFieldNull()) {
				Assert.notNull(val, "扩展字段不能为空：" + extField.getFieldCode());
			}
			if (val != null && val.toString().length() > extField.getFieldLen()) {
				Assert.isTrue(true, extField.getFieldCode() + "扩展字段长度不能超过" + extField.getFieldLen());
			}

			if (Long.class.getSimpleName().equalsIgnoreCase(extField.getFieldType())) {
				reqMap.getLong(extField.getFieldType());
			}
			if (Integer.class.getSimpleName().equalsIgnoreCase(extField.getFieldType())) {
				reqMap.getInteger(extField.getFieldType());
			}
			if (Float.class.getSimpleName().equalsIgnoreCase(extField.getFieldType())) {
				reqMap.getFloat(extField.getFieldType());
			}
			if (Double.class.getSimpleName().equalsIgnoreCase(extField.getFieldType())) {
				reqMap.getDouble(extField.getFieldType());
			}
		}
	}

}
