package com.quantgroup.asset.distribution.service.notify.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.common.collect.ImmutableMap;
import com.quantgroup.asset.distribution.service.asset.IBizAssetOrderService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.quantgroup.asset.distribution.enums.funding.FundingResult;
import com.quantgroup.asset.distribution.exception.QGException;
import com.quantgroup.asset.distribution.exception.QGExceptionType;
import com.quantgroup.asset.distribution.model.form.AssetForm;
import com.quantgroup.asset.distribution.service.alarm.IAlarmService;
import com.quantgroup.asset.distribution.service.httpclient.IHttpService;
import com.quantgroup.asset.distribution.service.notify.INotifyService;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class NotifyServiceImpl implements INotifyService{
	
	@Value("${isDebug}")
    private Boolean isDebug;
	@Value("${business.flow.url}")
	private String businessFlowURL;
	@Value("${rule.engine.url}")
	private String ruleEngineURL;

	@Autowired
	private IHttpService httpService;
	@Autowired
	private IAlarmService alarmService;
	@Autowired
	private IBizAssetOrderService bizAssetOrderService;
	
	@Override
	public void notifyFundServer(AssetForm assetForm, Map<String, Object> data) {
		// 测试环境也做通知
//		if (isDebug) { return; }
		Map<String, String> notifyMap = assetForm.transToNotifyMap(data);
		log.info("通知资金系统结果开始, uuid : {}, bizNo : {}, assetNo : {}, callbackUrl : {}, notifyForm : {}", assetForm.getUuid(), assetForm.getBizNo(), assetForm.getAssetNo(), assetForm.getCallbackUrl(), JSON.toJSONString(notifyMap));
		if (StringUtils.isEmpty(assetForm.getCallbackUrl())) { 
			log.info("通知资金系统结果失败，callbackUrl为空, uuid : {}, bizNo : {}, assetNo : {}, notifyForm : {}", assetForm.getUuid(), assetForm.getBizNo(), assetForm.getAssetNo(), JSON.toJSONString(notifyMap));
			throw new QGException(QGExceptionType.NOTIFY_FUND_SERVER_ERROR, assetForm.getUuid(), assetForm.getBizNo(), assetForm.getAssetNo());
		}
		Map<String, String> response = httpService.postHasResponse(assetForm.getCallbackUrl(), notifyMap);
		log.info("通知资金系统结果结束, uuid : {}, bizNo : {}, assetNo : {}, callbackUrl : {}, notifyForm : {}, response : {}", assetForm.getUuid(), assetForm.getBizNo(), assetForm.getAssetNo(), assetForm.getCallbackUrl(), JSON.toJSONString(notifyMap), JSON.toJSONString(response));
		if(response==null || response.size()==0 || !"200".equals(response.get("statusCode")) || (!"success".equals(response.get("response")) && (!JSONObject.isValidObject(response.get("response")) || 0 != JSONObject.parseObject(response.get("response")).getInteger("code").intValue()))) {
			throw new QGException(QGExceptionType.NOTIFY_FUND_SERVER_ERROR, assetForm.getUuid(), assetForm.getBizNo(), assetForm.getAssetNo());
		} else {
			bizAssetOrderService.finishAssetOrder(assetForm);
			//通知规则的引擎将白名单置为失效
			if ("1".equals(assetForm.getSpecialUserList())){
				notifyRuleEngine(assetForm);
			}
		}
	}

	private void notifyRuleEngine(AssetForm assetForm) {
		//现在只有一个多个加个逗号隔开
		String key =  "specialUserList";
		log.info("通知量子魔方将对应白名单置为失效开始, uuid : {}, bizNo : {}, assetNo : {}, key : {} ", assetForm.getUuid(), assetForm.getBizNo(), assetForm.getAssetNo(), key);
		Map<String, String> response = httpService.postHasResponse(ruleEngineURL + "/callback/event/specialUserList", ImmutableMap.of("keys",key,"uuid",assetForm.getUuid()));
		if(response==null || response.size()==0 || !"200".equals(response.get("statusCode")) || (!"0".equals(response.get("code")))) {
			log.error("通知量子魔方将对应白名单置为失效失败 , uuid : {}, bizNo : {}, assetNo : {}, key : {} ,response : {}", assetForm.getUuid(), assetForm.getBizNo(), assetForm.getAssetNo(), key,JSON.toJSONString(response));
			alarmService.dingtalkAlarm("Warn", "通知量子魔方使白名单失效异常", "uuid : "+ assetForm.getUuid() +"bizNo : " + assetForm.getBizNo());
		}
	}

	@Override
	public void notifyBusinessFlow(String bizNo, FundingResult fundingResult, String nextOperateDate) {
		try {
//			if (isDebug) { return; } 测试环境也保证通知
			log.info("通知业务流系统订单终态开始, bizNo : {}, fundingResult : {}, nextOperateDate : {}", bizNo, fundingResult.name(), nextOperateDate);
			String response = httpService.post(businessFlowURL + "/ex/inner/accept_info", new HashMap<String, String>(){{
				put("applyNo", bizNo);
				put("status", getNotifyBusinessFlowStatusByFundingResult(fundingResult) + "");
				put("type", "5");
				put("auditValidTime", nextOperateDate);
			}});
			log.info("通知业务流系统订单终态结束, bizNo : {}, fundingResult : {}, nextOperateDate : {}, response : {}", bizNo, fundingResult.name(), nextOperateDate, response);
			JSONObject data = null;
			if (StringUtils.isEmpty(response) || (data = JSON.parseObject(response)).getInteger("code") != 0) {
				throw new QGException(QGExceptionType.NOTIFY_BUSINESS_FLOW_ERROR, bizNo, fundingResult.name());
	    	}
		} catch (QGException qe) {
			log.error("资产分发订单终态通知业务流系统出现错误, 错误信息 : {}, bizNo : {}, fundingResult : {}", qe.qgExceptionType.code + "->" + qe.detail, bizNo, fundingResult.name());
			alarmService.dingtalkAlarm("Warn", "通知业务流系统订单终态出现错误", "错误信息 : " + qe.qgExceptionType.code + "->" + qe.detail + " , bizNo : " + bizNo + " , " + "status : " + fundingResult.name());
		} catch (Exception e) {
			log.error("资产分发订单终态通知业务流系统异常, bizNo : {}, fundingResult : {}", bizNo, fundingResult.name());
			alarmService.dingtalkAlarm("Warn", "通知业务流系统订单终态异常", "bizNo : " + bizNo + " , " + "status : " + fundingResult.name());
		}
	}
	
	/**
	 * @return
	 * @param fundingResult
	 */
	private int getNotifyBusinessFlowStatusByFundingResult(FundingResult fundingResult) {
		if (fundingResult == FundingResult.FUAD_ASSIGN_SUCC) {
			return 1;
		} else if (fundingResult == FundingResult.REJECT) {
			return 0;
		} else if (fundingResult == FundingResult.CANCEL_LOAN) {
			return 2;
		} else if (fundingResult == FundingResult.HANG_UP) {
			return 3;
		} else {
			return -1;
		}
	}
}
