package com.qunzhixinxi.hnqz.admin.service.retry.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.logosdata.security.util.SignUtils;
import com.qunzhixinxi.hnqz.admin.api.constant.CacheConstants;
import com.qunzhixinxi.hnqz.admin.entity.WmScorePackageSettleNote;
import com.qunzhixinxi.hnqz.admin.entity.WmTask;
import com.qunzhixinxi.hnqz.admin.entity.WmTaskContent;
import com.qunzhixinxi.hnqz.admin.entity.input.Record;
import com.qunzhixinxi.hnqz.admin.entity.input.TaskSettleBatch;
import com.qunzhixinxi.hnqz.admin.entity.input.TaskSettleInfo;
import com.qunzhixinxi.hnqz.admin.service.WmTaskContentService;
import com.qunzhixinxi.hnqz.admin.service.WmTaskService;
import com.qunzhixinxi.hnqz.admin.service.retry.PartyARetryService;
import com.qunzhixinxi.hnqz.common.taxhelper.entity.model.EncryptLoginInfo;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 甲方服务重试实现类
 *
 * @author Hengchen.Sun
 * @date 2021.06.15
 */
@Service
@Slf4j
@AllArgsConstructor
public class PartyARetryServiceImpl implements PartyARetryService {

	private final StringRedisTemplate redisTemplate;
	private final WmTaskService wmTaskService;
	private final WmTaskContentService wmTaskContentService;

	/**
	 * 执行认证回调（可重试）
	 * 最多重试三次，按照 2秒，4秒后退机制重试
	 * @param params 回调参数
	 */
	@Override
	@Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000L, multiplier = 2))
	public void doRetryableCertCallBack(Map<String, Object> params) {

		Assert.notEmpty(params);
		String token = login();
		params.put("token", token);
		ResponseEntity<String> responseEntity = getResp(params, PartyARetryService.WENWEN_CERTIFICATION_RESULTS_URL);
		HttpStatus statusCode = responseEntity.getStatusCode();
		if (HttpStatus.OK.equals(statusCode)) {
			String body = responseEntity.getBody();
			JSONObject jsonObject = JSONUtil.parseObj(body);
			String status = jsonObject.getStr("status");
			JSONObject data = jsonObject.getJSONObject("data");
			if (!"success".equals(status)) {
				String msg = data.getStr("message");
				log.error("问问风湿认证回调失败:{}", msg);
				throw new RuntimeException("问问风湿认证回调失败");
			}
		} else {
			log.error("问问风湿认证回调请求失败");
			throw new RuntimeException("问问风湿认证回调请求失败");
		}


	}

	/**
	 *  执行结算回调（可重试）
	 * @param noteList 结算记录列表
	 */
	@Override
	@Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 2000L, multiplier = 2))
	public void doRetryableSettleNoteCallBack(List<WmScorePackageSettleNote> noteList) {

		Assert.notEmpty(noteList);
		String token = login();

		// 封装证据链
		// TaskSettleBatch tsb = new TaskSettleBatch();
		//
		// tsb.setDeptId();
		// tsb.setScorePackageStatusId(Integer.valueOf(noteList.get(0).getPackageStatusId()));
		// tsb.setPackageId(Integer.valueOf(noteList.get(0).getPackageId()));

		List<WmTaskContent> tsb = noteList.stream().map(note -> {
			WmTask task = wmTaskService.getById(note.getTaskId());
			return wmTaskContentService.getById(task.getTaskContentId());
		}).collect(Collectors.toList());

		Map<String, Object> params = new HashMap<>();
		params.put("token", token);
		params.put("code", "2000");
		params.put("data", JSONUtil.toJsonStr(tsb));
		params.put("success_msg", "SUCCESS");
		ResponseEntity<String> resp = getResp(params, PartyARetryService.WENWEN_SETTLEMENT_RESULTS_URL);
		if (HttpStatus.OK.equals(resp.getStatusCode())) {
			String body = resp.getBody();
			JSONObject jsonObject = JSONUtil.parseObj(body);
			String status = jsonObject.getStr("status");
			JSONObject data = jsonObject.getJSONObject("data");
			if (!"success".equals(status)) {
				String msg = data.getStr("message");
				log.error("问问风湿结算回调失败:{}", msg);
				throw new RuntimeException("问问风湿结算回调失败");
			}
		} else {
			log.error("问问风湿认证回调请求失败");
			throw new RuntimeException("问问风湿认证回调请求失败");
		}

	}


	/**
	 * 发起请求
	 *
	 * @param params 请求参数
	 * @param url    请求地址
	 * @return 响应结果
	 */
	private ResponseEntity<String> getResp(Map<String, Object> params, String url) {
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		HttpEntity<Object> httpEntity = new HttpEntity<>(params, headers);
		return new RestTemplate().exchange(url, HttpMethod.POST, httpEntity, String.class);
	}

	/**
	 * 问问风湿登陆
	 *
	 * @return 获取登陆token
	 */
	private String login() {

		String token = redisTemplate.opsForValue().get(CacheConstants.WENWEN_LOGIN_KEY);
		if (StringUtils.isEmpty(token)) {
			Map<String, Object> params = new HashMap<>(2);
			params.put("appid", PartyARetryService.WENWEN_APP_ID);
			params.put("appsecret", PartyARetryService.WENWEN_APP_SECRET);
			ResponseEntity<String> responseEntity = getResp(params, PartyARetryService.WENWEN_LOGIN_URL);
			HttpStatus statusCode = responseEntity.getStatusCode();
			if (HttpStatus.OK.equals(statusCode)) {
				String body = responseEntity.getBody();
				JSONObject jsonObject = JSONUtil.parseObj(body);
				String status = jsonObject.getStr("status");
				JSONObject data = jsonObject.getJSONObject("data");
				if ("fail".equals(status)) {
					String msg = data.getStr("message");
					log.error("登陆失败:{}", msg);
					throw new RuntimeException("问问风湿登陆失败");
				} else {
					token = data.getStr("token");
					redisTemplate.opsForValue().set(CacheConstants.WENWEN_LOGIN_KEY, token, 2L, TimeUnit.HOURS);
				}
			} else {
				log.error("问问风湿请求失败");
				throw new RuntimeException("问问风湿请求失败");
			}
		}
		return token;
	}
}
