package com.yeejoin.amos.boot.module.hygf.biz.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qiyuesuo.sdk.v2.SdkClient;
import com.qiyuesuo.sdk.v2.bean.*;
import com.qiyuesuo.sdk.v2.bean.vo.DocumentUrlVO;
import com.qiyuesuo.sdk.v2.exception.BaseSdkException;
import com.qiyuesuo.sdk.v2.json.JSONUtils;
import com.qiyuesuo.sdk.v2.request.*;
import com.qiyuesuo.sdk.v2.response.*;
import com.yeejoin.amos.boot.module.hygf.api.dto.ContractDataDto;
import com.yeejoin.amos.boot.module.hygf.api.dto.TemplateParamDto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: tw
 * @createDate: 2023/8/21
 */
@Service
public class QiyuesuoServiceImpl {

	@Value("${qiyuesuo.serverUrl}")
	String serverUrl;
	@Value("${qiyuesuo.accessKey}")
	String accessKey;
	@Value("${qiyuesuo.accessSecret}")
	String accessSecret;

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

	/***
	 *
	 * 个人权限
	 */

	public SdkResponse<MiniappTicketResult> getSdkResponse(UserAuthMiniappTicketRequest request) {
		SdkClient sdkClient = new SdkClient(serverUrl, accessKey, accessSecret);

		String response = null;
		try {
			response = sdkClient.service(request);
		} catch (Exception e) {
			throw new BaseSdkException("调用接口错误，错误原因：" + e.getMessage());
		}
		SdkResponse<MiniappTicketResult> result = JSONUtils.toQysResponse(response, MiniappTicketResult.class);
		if (!result.getCode().equals(0)) {
			throw new BaseSdkException("获取个人认证Ticket失败，失败原因：" + result.getCode() + "," + result.getMessage());
		}
		return result;
	}

	/**
	 * 合同授权
	 *
	 **/

	public SdkResponse<MiniappTicketResult> getContractSdkResponse(ContractMiniappTicketRequest request) {
		SdkClient sdkClient = new SdkClient(serverUrl, accessKey, accessSecret);
		String response = null;
		try {
			response = sdkClient.service(request);
		} catch (Exception e) {
			throw new BaseSdkException("调用接口错误，错误原因：" + e.getMessage());
		}
		SdkResponse<MiniappTicketResult> result = JSONUtils.toQysResponse(response, MiniappTicketResult.class);
		if (!result.getCode().equals(0)) {
			throw new BaseSdkException("获取合同签署Ticket失败，失败原因：" + result.getCode() + "," + result.getMessage());
		}
		return result;
	}

	/**
	 * 获取合同浏览令牌
	 * 
	 * @param request
	 * @return
	 */
	public SdkResponse<MiniappTicketResult> getContractTokenTicket(Long sequenceNbr) {
		SdkClient sdkClient = new SdkClient(serverUrl, accessKey, accessSecret);
		ContractMiniappViewTicketRequest request = new ContractMiniappViewTicketRequest(sequenceNbr);
		String response = null;
		try {
			response = sdkClient.service(request);
		} catch (Exception e) {
			throw new BaseSdkException("调用接口错误，错误原因：" + e.getMessage());
		}
		SdkResponse<MiniappTicketResult> result = JSONUtils.toQysResponse(response, MiniappTicketResult.class);
		if (!result.getCode().equals(0)) {
			throw new BaseSdkException("获取合同签署Ticket失败，失败原因：" + result.getCode() + "," + result.getMessage());
		}
		logger.info("获取合同签署Ticket成功，Ticket:" + result.getResult().getTicket());
		return result;
	}

	/**
	 * 创建合同
	 *
	 *
	 **/

	public Long addContract(ContractDataDto contractDataDto, List<TemplateParamDto> templateParam,List<User> corpOperators) {
		SdkResponse<Contract> responseObj = null;
		// 返回结果
		Contract result = new Contract();
		String username = contractDataDto.getUsername();
		String contact = contractDataDto.getContact();
		String IDCard = contractDataDto.getIDCard();
		String subject = contractDataDto.getSubject();
		String endTime = contractDataDto.getEndTime();
		String expireTime = contractDataDto.getExpireTime();
		String category = contractDataDto.getCategory();
		String companyTenantName = contractDataDto.getCompanyTenantName();
		String companyUsername = contractDataDto.getCompanyUsername();
		String companyContact = contractDataDto.getCompanyContact();
		Long emplateId = contractDataDto.getEmplateId();
		String companykeyword = contractDataDto.getCompanykeyword();
		Integer companykeywordIndex = contractDataDto.getCompanyKeywordIndex();
		Integer companyPage = contractDataDto.getCompanyPage();
		Double companyOffsetX = contractDataDto.getCompanyOffsetX();
		Double companyOffsetY = contractDataDto.getCompanyOffsetY();
		String personalkeyword = contractDataDto.getPersonalkeyword();
		Integer personalkeywordIndex = contractDataDto.getPersonalKeywordIndex();
		Integer personalPage = contractDataDto.getPersonalPage();
		Double personalOffsetX = contractDataDto.getPersonalOffsetX();
		Double personalOffsetY = contractDataDto.getPersonalOffsetY();
		List<Long> corpSealIds = contractDataDto.getSealId();
		try {
			SdkClient sdkClient = new SdkClient(serverUrl, accessKey, accessSecret);
			// 合同基本参数
			// 进行日期格式化
			Contract contract = new Contract();
			contract.setSubject(subject);
			contract.setDescription(subject);
			contract.setCategory(new Category(category));
			contract.setSend(false);
			// 个人
			Signatory signatory1 = new Signatory();
			signatory1.setTenantName(username);
			signatory1.setTenantType("PERSONAL");
			signatory1.setReceiver(new User(username, contact, "MOBILE"));
			signatory1.setSerialNo(1);

			// 对接方
			Signatory signatory2 = new Signatory();
			signatory2.setTenantName(companyTenantName);
			signatory2.setTenantType("COMPANY");
			signatory2.setReceiver(new User(companyUsername, companyContact, "MOBILE"));
			signatory2.setSerialNo(2);
			Action action = new Action("COMPANY", 0);
			// 指定印章
			action.setCorpSealIds(corpSealIds);
			//指定操作人
			action.setCorpOperators(corpOperators);
			signatory2.addAction(action);
			// 设置签署方
			contract.addSignatory(signatory1);
			contract.addSignatory(signatory2);

			// 创建合同
			ContractDraftRequest request = new ContractDraftRequest(contract);
			logger.info("创建草稿合同调用前" + JSON.toJSONString(request));
			String response = sdkClient.service(request);
			responseObj = JSONUtils.toQysResponse(response, Contract.class);

			logger.info("创建草稿合同调用后" + JSON.toJSONString(responseObj));
		} catch (Exception e) {
			e.printStackTrace();
			throw new BadRequest("创建草稿合同失败");
		}
		if (responseObj.getCode() == 0) {
			result = responseObj.getResult();
			logger.info(JSON.toJSONString(responseObj));
		} else {
			String error = "请求失败，错误码:"+responseObj.getCode()+",错误信息:"+responseObj.getMessage();
			logger.info(error);
			throw new BadRequest(error);
		}
		DocumentAddResult documentAddResult = this.getDocumentAddResult(result.getId(), subject, templateParam,
				emplateId);
		List<Signatory> list = result.getSignatories();
		Long ActionId = null;
		Long SignatoryId = null;
		for (Signatory signatory : list) {
			if (signatory.getTenantType().equals("COMPANY")) {
				ActionId = signatory.getActions().get(0).getId();
			} else {
				SignatoryId = signatory.getId();
			}
		}
		// 发起时可以设置签署位置
		Stamper stamper = new Stamper();
		stamper.setActionId(ActionId);
		stamper.setDocumentId(documentAddResult.getDocumentId());
		stamper.setKeyword(companykeyword);
		stamper.setType("COMPANY");
		// stamper.setPage(companyPage);
		stamper.setOffsetX(companyOffsetX);
		stamper.setOffsetY(companyOffsetY);
		stamper.setKeywordIndex(companykeywordIndex);
		Stamper stamper2 = new Stamper();
		stamper2.setSignatoryId(SignatoryId);
		stamper2.setDocumentId(documentAddResult.getDocumentId());
		stamper2.setKeyword(personalkeyword);
		stamper2.setType("PERSONAL");
		// stamper2.setPage(personalPage);
		stamper2.setOffsetX(personalOffsetX);
		stamper2.setOffsetY(personalOffsetY);
		stamper2.setKeywordIndex(personalkeywordIndex);
		List<Stamper> stampers = new ArrayList<>();
		stampers.add(stamper);
		stampers.add(stamper2);
		//发起合同
		SdkResponse<Object> data = this.getSdkResponse(result.getId(), stampers);
		return result.getId();
	}

	public DocumentAddResult getDocumentAddResult(Long contractId, String subject, List<TemplateParamDto> templateParam,
			Long emplateId) {

		DocumentAddResult result = null;
		SdkResponse<DocumentAddResult> responseObj = null;
		try {
			SdkClient sdkClient = new SdkClient(serverUrl, accessKey, accessSecret);
			// 添加合同文档
			List<TemplateParam> params = new ArrayList<>();
			for (TemplateParamDto templateParamDto : templateParam) {
				if (templateParamDto.getValue() != null) {
					params.add(new TemplateParam(templateParamDto.getKey(), templateParamDto.getValue()));
				}
			}
			logger.info("添加合同文档参数" + JSON.toJSONString(params));
			DocumentAddByTemplateRequest request = new DocumentAddByTemplateRequest(contractId, emplateId, params,
					subject);
			logger.info("添加合同文档前" + JSON.toJSONString(request));
			String response = sdkClient.service(request);
			responseObj = JSONUtils.toQysResponse(response, DocumentAddResult.class);
			logger.info("添加合同文档后" + JSON.toJSONString(responseObj));

		} catch (Exception e) {
			e.printStackTrace();
			throw new BadRequest("添加合同文档失败");
		}
		if (responseObj != null && responseObj.getCode() == 0) {
			result = responseObj.getResult();
			logger.info("添加合同文档成功，文档ID:{}", JSON.toJSONString(result));
		} else {
			throw new BadRequest("添加合同文档" + responseObj.getMessage());
		}
		return result;
	}

	public SdkResponse<Object> getSdkResponse(Long contractId, List<Stamper> stampers) {
		// 发起合同
		SdkResponse<Object> responseObj = null;
		try {

			SdkClient sdkClient = new SdkClient(serverUrl, accessKey, accessSecret);
			ContractSendRequest request = new ContractSendRequest(contractId, stampers);
			logger.info("请求契约锁发起合同前" + JSON.toJSONString(request));
			String response = sdkClient.service(request);
			responseObj = JSONUtils.toQysResponse(response);
		} catch (Exception e) {
			e.printStackTrace();
			throw new BadRequest("请求契约锁发起合同接口失败");
		}
		logger.info("请求契约锁发起合同后" + JSON.toJSONString(responseObj));
		if (responseObj != null && responseObj.getCode() == 0) {
			logger.info("请求契约锁发起合同成功");
		} else {
			throw new BadRequest("请求契约锁发起合同失败" + responseObj.getMessage());
		}

		return responseObj;
	}

	public String getPageUrl(Long contractId) {
		String url = null;
		SdkClient sdkClient = new SdkClient(serverUrl, accessKey, accessSecret);
		ContractViewPageRequest request = new ContractViewPageRequest(contractId);
		String response = sdkClient.service(request);
		SdkResponse<ContractPageResult> responseObj = JSONUtils.toQysResponse(response, ContractPageResult.class);
		if (responseObj.getCode() == 0) {
			ContractPageResult result = responseObj.getResult();
			url = result.getPageUrl();
			logger.info("合同页面地址为:{}", result.getPageUrl());
		} else {
			logger.info("请求失败，错误码:{}，错误信息:{}", responseObj.getCode(), responseObj.getMessage());
		}
		return url;
	}

	public String getdownloadUrl(Long contractId) {

		String url = null;
		SdkClient sdkClient = new SdkClient(serverUrl, accessKey, accessSecret);
		ContractDownloadUrlRequest downloadRequest = new ContractDownloadUrlRequest(contractId);
		String response = sdkClient.service(downloadRequest);
		SdkResponse<ContractDownloadUrlResult> responseObj = JSONUtils.toQysResponse(response,
				ContractDownloadUrlResult.class);
		if (responseObj.getCode().equals(0)) {

			List<DocumentUrlVO> downloadUrls = responseObj.getResult().getDownloadUrls();
			for (DocumentUrlVO vo : downloadUrls) {
				if ("CONTRACT".equals(vo.getDownloadItems())) {
					url = vo.getDownloadUrl();
				}
			}
		} else {
			throw new BadRequest("请求失败");
		}
		return url;
	}

	public String getUrl(Long contractId) {
		String url = null;
		SdkClient sdkClient = new SdkClient(serverUrl, accessKey, accessSecret);
		ContractViewPageRequest request = new ContractViewPageRequest(contractId);
		String response = sdkClient.service(request);
		SdkResponse<ContractPageResult> responseObj = JSONUtils.toQysResponse(response, ContractPageResult.class);
		if (responseObj.getCode() == 0) {
			ContractPageResult result = responseObj.getResult();
			url = result.getPageUrl();
		} else {
			logger.info("请求失败，错误码:{}，错误信息:{}", responseObj.getCode(), responseObj.getMessage());
		}
		return url;
	}

	public Map<Long,Contract> getContractMap(){
		List<Contract> list =new ArrayList<>();
		Integer pageNo = 0;
		try {
			do {
				SdkClient sdkClient = new SdkClient(serverUrl, accessKey, accessSecret);
				ContractListRequest contractListRequest = new ContractListRequest();
				contractListRequest.setSelectOffset(pageNo*1000);
				String response = sdkClient.service(contractListRequest);
				SdkResponse<ContractListResult> responseObj = JSONUtils.toQysResponse(response, ContractListResult.class);
				if (responseObj.getCode() == 0) {
					ContractListResult result = responseObj.getResult();
					list.addAll(result.getList());
					//处理其他页数的数据
					Integer selectOffset =(pageNo+1)*1000;
					if (result.getTotalCount() <= selectOffset){
						break;
					} else {
						pageNo++;
					}
				} else {
					logger.error("请求失败，错误码:{}，错误信息:{}", responseObj.getCode(), responseObj.getMessage());
				}
			}while (true);
		} catch (Exception e) {
			logger.error(e.getMessage(),e);
		}
		return list.stream().collect(Collectors.toMap(Contract::getId, Function.identity(), (existing, replacement) -> existing));
	}

}
