package com.bocloud.ims.service.internal.worker;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson.JSON;
import com.bocloud.common.enums.BoCloudMethod;
import com.bocloud.common.enums.PostDataFormat;
import com.bocloud.common.http.HttpClient;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.Result;
import com.bocloud.service.core.Service;
import com.bocloud.service.http.model.RemoteService;
import com.bocloud.service.http.model.ServiceParam;

/**
 * 同步调用Worker服务专用的远程服务
 */
public class WorkerRemoteService extends RemoteService {
	private static Logger logger = LoggerFactory.getLogger(WorkerRemoteService.class);

	public WorkerRemoteService(Service service, boolean exist) {
		super(service, exist);
	}

	public WorkerRemoteService(Service service, ServiceParam param, boolean exist, String url, BoCloudMethod method) {
		super(service, param, exist, url, method);
	}

	@Override
	public BocloudResult invoke() {
		boolean exist = super.isExist();
		String url = super.getUrl();
		BoCloudMethod method = super.getMethod();
		ServiceParam param = super.getParam();
		PostDataFormat dataFormat = super.getDataFormat();
		Service service = super.getService();

		if ((!exist) || (!StringUtils.isNotEmpty(url)) || (method == null)) {
			logger.error("Remote service [{}] does not exist!", service.getName());
			return new BocloudResult(false, "【" + service.getName() + "】服务未找到！", "404", "远端服务异常，请稍后重试！");
		}
		Result response = null;
		HttpClient client = new HttpClient(10 * 60 * 1000);
		switch (method.getMethod()) {
		case GET:
			response = client.get(param.getHeaders(), param.getParams(), url);
			break;
		case POST:
			client.setDataFormat(dataFormat);
			response = client.post(param.getHeaders(), param.getParams(), url);
			break;
		case DELETE:
			response = client.delete(param.getHeaders(), param.getParams(), url);
			break;
		case PUT:
			response = client.put(param.getHeaders(), param.getParams(), url);
			break;
		case PATCH:
			response = client.patch(param.getHeaders(), param.getParams(), url);
			break;
		case TRACE:
			response = client.trace(param.getHeaders(), param.getParams(), url);
			break;
		default:
			response = client.get(param.getHeaders(), param.getParams(), url);
		}
		return getResult(response);
	}

	private BocloudResult getResult(Result response) {
		String url = super.getUrl();
		if (response.isSuccess()) {
			try {
				WorkerResult result = JSON.parseObject(response.getMessage(), WorkerResult.class);
				boolean success = result.getSuccess();
				String message = result.getMessage();
				List<WorkerHostResult> hostResults = result.getData();
				if (!success) {
					message = getDetailedErrorMsg(hostResults, message);
				}
				return new BocloudResult(success, hostResults, message);
			} catch (Exception e) {
				logger.error("Remote service[{}] 返回结果无法转化为WorkerResult对象，返回结果为:[{}]", url, response.getMessage());
				return new BocloudResult(false, "远程服务返回结果无法转化为WorkerResult对象");
			}
		}
		logger.error("Remote service[{}] invoke Error:[{}]", url, response.getErrorMsg());
		return new BocloudResult(false, response.getErrorMsg());
	}

	/**
	 * 获取worker服务返回结果中更详细的提示信息
	 * 
	 * @author sxp
	 * @since Jan 29, 2018
	 */
	private String getDetailedErrorMsg(List<WorkerHostResult> hostResults, String defaultMessage) {
		if (hostResults == null || hostResults.size() == 0) {
			return defaultMessage;
		}

		StringBuilder sb = new StringBuilder();
		Boolean success;
		Map<String, Object> message;
		Object msgObj;
		String errorMsg;

		for (WorkerHostResult hostRst : hostResults) {
			if (StringUtils.isEmpty(hostRst.getHost())) {
				continue;
			}
			success = hostRst.getSuccess();

			if (success) {
				continue;
			} else {
				message = hostRst.getMessage();
				msgObj = message.get("msg");
				if (msgObj != null) {
					errorMsg = String.valueOf(msgObj);
				} else {
					errorMsg = "";
				}

				if (sb.length() > 0) {
					sb.append("；");
				}
				sb.append("[");
				sb.append(hostRst.getHost());
				sb.append("]");
				sb.append("执行失败，原因：");
				sb.append(errorMsg);
			}
		}

		return sb.toString();
	}
}
