package com.leanwo.activiti.service.base.impl;

import java.util.Date;

import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import com.leanwo.activiti.dto.BaseResponse;
import com.leanwo.activiti.dto.base.TaskDefineDto;
import com.leanwo.activiti.dto.base.TaskInstanceSaveRequest;
import com.leanwo.activiti.dto.base.TaskInstanceStatus;
import com.leanwo.activiti.dto.base.TaskInstanceUpdateRequest;
import com.leanwo.activiti.service.base.HttpTaskEngine;
import com.leanwo.activiti.service.base.QuartzEngine;
import com.leanwo.activiti.service.base.TokenService;
import com.leanwo.activiti.util.GsonUtil;
import com.leanwo.activiti.util.LoginContext;
import com.leanwo.activiti.util.LoginContextUtil;
import com.leanwo.activiti.util.SpringUtil;
import com.leanwo.activiti.util.StringUtil;
import com.leanwo.activiti.util.TokenUtil;

/**
 * Http任务自动运行
 * 
 * @author YangZhiJie
 *
 */
public class HttpTaskJob implements Job {

	private static Logger logger = LoggerFactory.getLogger(HttpTaskJob.class);

	@Override
	public void execute(JobExecutionContext context) throws JobExecutionException {
		JobDetail detail = context.getJobDetail();
		JobDataMap map = detail.getJobDataMap();

		TaskDefineDto taskDefineDto = (TaskDefineDto) map.get(QuartzEngine.HttpTask);
		Long accountId = map.getLong(QuartzEngine.AccountId);
		LoginContext loginContext = new LoginContext();
		loginContext.setAccountId(accountId);
		LoginContextUtil.setLoginContext(loginContext);

		TokenService tokenService = (TokenService) SpringUtil.getSingleBean(TokenService.class);
		String tempToken = tokenService.generateTempToken();
		TokenUtil.setToken(tempToken);

		logger.info(taskDefineDto.toString() + "开始运行。");

		if (!SpringUtil.initSuccess()) {
			logger.info("Spring 容器正在启动，无法运行流程。");
			return;
		}

		if (StringUtil.isEmpty(TokenUtil.getToken())) {
			logger.info("未获取到token。");
			return;
		}

		String requestType = taskDefineDto.getHttpRequestType().getDisplayName();
		if (requestType == null) {
			logger.error(taskDefineDto.toString() + "未定义请求类型");
			return;
		}

		requestType = requestType.toLowerCase();
		if (!requestType.equals("get") && !requestType.equals("post")) {
			logger.error(taskDefineDto.toString() + "请求类型必须是get或者post");
			return;
		}

		HttpTaskEngine httpTaskEngine = (HttpTaskEngine) SpringUtil.getSingleBean(HttpTaskEngine.class);

		if (httpTaskEngine == null) {
			logger.error("获取bean:'httpTaskEngine'失败");
			return;
		}

		Long timeSerialNumber = System.currentTimeMillis();

		try {
			RestTemplate restTemplate = new RestTemplate();

			HttpHeaders httpHeaders = new HttpHeaders();
			MediaType mediaType = MediaType.parseMediaType("application/json; charset=UTF-8");
			httpHeaders.setContentType(mediaType);
			httpHeaders.add("account", String.valueOf(accountId));
			httpHeaders.add("token", TokenUtil.getToken());

			HttpEntity requestEntity = new HttpEntity(httpHeaders);

			String url = getApiUrl(taskDefineDto.getHttpRequestUrl());

			HttpMethod httpMethod = null;
			if (requestType.equals("get")) {
				httpMethod = HttpMethod.GET;
			} else if (requestType.equals("post")) {
				httpMethod = HttpMethod.POST;
			}

			// 生成流程实例
			httpTaskEngine.addTaskInstance(timeSerialNumber, taskDefineDto);

			ResponseEntity<String> response = restTemplate.exchange(url, httpMethod, requestEntity, String.class);

			String responseJosn = null;
			TaskInstanceStatus taskInstanceStatus = null;
			if (response != null) {
				responseJosn = response.getBody();
			}

			if (StringUtil.isNotEmpty(responseJosn)) {
				BaseResponse baseResponse = GsonUtil.getGson().fromJson(responseJosn, BaseResponse.class);
				if (baseResponse == null) {
					taskInstanceStatus = TaskInstanceStatus.FAIL;
					responseJosn = "HTTP任务执行返回结果转换BaseRespone类失败。";
				} else {
					if (baseResponse.getErrorCode() == 0) {
						taskInstanceStatus = TaskInstanceStatus.SUCCESS;
					} else {
						taskInstanceStatus = TaskInstanceStatus.FAIL;
					}
				}
			} else {
				responseJosn = taskDefineDto.toString() + "未获取到HTTP任务执行结果。";
				taskInstanceStatus = TaskInstanceStatus.FAIL;
			}
			// 更新流程实例
			httpTaskEngine.updateTaskInstance(timeSerialNumber, responseJosn, taskInstanceStatus, taskDefineDto);
		} catch (Throwable e) {
			// 更新流程实例
			httpTaskEngine.updateTaskInstance(timeSerialNumber, "运行失败," + e.getMessage(), TaskInstanceStatus.FAIL,
					taskDefineDto);
		} finally {
			logger.debug(taskDefineDto.toString() + "运行完毕。");
		}
	}

	/**
	 * 获取服务器路由地址
	 * 
	 * @param url
	 * @return
	 */
	private String getApiUrl(String url) {
		String apiUrl = "http://127.0.0.1:83/api/" + url;
		return apiUrl;
	}
}
