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

import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Base64;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.yeejoin.amos.boot.biz.common.excel.ExcelUtil;
import com.yeejoin.amos.boot.module.hygf.api.dto.HistoryPeasantHouseholdDto;
import com.yeejoin.amos.boot.module.hygf.api.dto.HygfIcbcRecordExportDTO;
import com.yeejoin.amos.boot.module.hygf.api.entity.PowerStationEngineeringInfo;
import com.yeejoin.amos.boot.module.hygf.api.mapper.HouseholdContractMapper;
import com.yeejoin.amos.boot.module.hygf.api.mapper.PowerStationEngineeringInfoMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.typroject.tyboot.core.foundation.utils.Bean;
import org.typroject.tyboot.core.rdbms.service.BaseService;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.icbc.api.DefaultIcbcClient;
import com.icbc.api.IcbcApiException;
import com.icbc.api.IcbcConstants;
import com.icbc.api.UiIcbcClient;
import com.icbc.api.request.JftApiUserEntrustopenacctQueryRequestV1;
import com.icbc.api.request.JftUiUserEntrustopenacctSubmitRequestV1;
import com.icbc.api.response.JftApiUserEntrustopenacctQueryResponseV1;
import com.icbc.api.utils.IcbcSignature;
import com.icbc.api.utils.WebUtils;
import com.yeejoin.amos.boot.module.hygf.api.Enum.IcbcEnum;
import com.yeejoin.amos.boot.module.hygf.api.dto.HygfIcbcRecordDTO;
import com.yeejoin.amos.boot.module.hygf.api.dto.HygfIcbcRecordQueryDTO;
import com.yeejoin.amos.boot.module.hygf.api.entity.HygfIcbcRecord;
import com.yeejoin.amos.boot.module.hygf.api.entity.HygfIcbcRequest;
import com.yeejoin.amos.boot.module.hygf.api.entity.PeasantHousehold;
import com.yeejoin.amos.boot.module.hygf.api.mapper.HygfIcbcRecordMapper;
import com.yeejoin.amos.boot.module.hygf.api.mapper.HygfIcbcRequestMapper;
import com.yeejoin.amos.boot.module.hygf.api.service.IHygfIcbcService;

import lombok.extern.slf4j.Slf4j;

/**
 * 并网信息服务实现类
 *
 * @author system_generator
 * @date 2024-01-12
 */
@Service
@Slf4j
public class HygfIcbcServiceImpl extends BaseService<HygfIcbcRecordDTO, HygfIcbcRecord, HygfIcbcRecordMapper>

		implements IHygfIcbcService {

	private static final String trxChannel = "05"; // 05表示小程序

	// 正式环境
//    private static  final String APP_ID = "11000000000000028870";
//    private static final String corpNo = "020240710000001169";
//    private static final String MY_PRIVATE_KEY = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDAlcIeANdqipul3/qAIRlknSacHiFCMzLzUJisGcr9ipm3p2rir8WDsac2MxgtUt+f89SGNoWyjv4q0/QAKQQTd5U3KuGAksCJLBGVibuFe7G7YGYVezUksjvocvp8GIinCIkzq67KL2SOpGXAu3s+282rx8AxdTZA/EhXQvbORbWz5+DamyY+wS7Maa8KmIOb6WZPtiXgENZxDHAafrqW8Gt1BnVfJNf5yS5J9Wl+LcR1EPvi5iH8dSIdn1ZMVupoREjV/DvItSogVehsqTRZWuekAo2xH9YEli1UMG/l3deViRn/A4VmPPzdv0xXpn/yO+OTjWez+KmSmJfAZXBvAgMBAAECggEABRYviWFWTz8X+1qeIDI/nHO2KFt3X2tAxkJztd/8h5PYmYw3e4NPATp5Ayp4UgIlW/ExxNW91EiImBL/F939eJIpA8sDJ8U4hqb+U+fOZyksOZnDOIAHmE+I24vl588yFM9Z6F55gGeeDVJ0SZHqIG/nz8i339aLt02yj3N6V1peQugBP6L9arcD+gVu4F70whkqW+lHBK/WzX1OazqEx3Ip175jqzi9/0vO/h/kqnGGXuMi2VeuAPsa+d0a6lf/FScxqCt3t6dCkJ5DPA1MCj81dPi5ZfCM/vE0N8I6LEV+RyC7bb4YVO/PoicFjb2j8vfLvldOUrsvkNH51dZusQKBgQDpMHacOBpIuVzEFfNtS9SgA96cUV6NCSmHoQppJ/p9xKzY4DpcqoOCIBT4WCvVe6PeN5mrjzt8Q5gJWxiq0tVgIF9k8GjLmuiJ2v4Qh8aUmlRwn0T0DYiX/Y7uzX+pRlkpoKrSktlTOT9vmGwZDGDk0h2+H3hZ3YQEucfA6bhHmQKBgQDTbHrbr1WsUR9lrdLaGi/Uphpl3BXLuCnJXav3yIZOktO5V68MfPZXLP7aaNtbK3n0YHD+Uv8wpHBBSWQYjVYlGdvlniA/W1pr73GZJECFfS1BmmFC4GG3E92D5IkmrcPlUuz8XxKrlwHnfW1F0MoDvhp930vS0tS6u+WYTt9dRwKBgCeEQPVkRIACeYf5OFFTQmsDfNv8pgs8fD8xuTPsxHQ/uhLenMVLWBHbIfKb7oG0/CYSQgZitW/vfHpJZ7q7E9HAaqoOW5P1YmbKJ7fhanOQW7LiKqs5B+bJ30j0piendkCpq4kXvaBu2SMuL1NnV5wvRz8K0jhYY6DxYrp8YPAxAoGAZxWTaZ25tgTvvBHeprzx6Ur7wAJpFiU7KpVjjbLV2WW5mbro/LvJGIQ11qQdn/w4wDBtp3MsPblPimWQSnBPOlO7Zd+NdZbDJbFfv/1vACcic8Qj/AmPW0ZyUSaSwKskwqGGLx7j6Yn9QbNkHhBJDz4XiJvhSm/FjS6kKXj7a20CgYEArnEiPmL5g1Ca/qKK9ql8Q6P9gipIfGGpaFu23y0trbcFpVn8Oos/ic0Jgw4Xiz+rqvb6bW2V6lqBJ+9/kdn0i7zlZxKNpYsW2xFgi04OU3d5HkGL16Y1rpqMYYEhjFaOIn7J8P046UYR99yaybgQd18TE6oFrX8OL5uY8M4ge4Y=";
//    private static final String serviceUrl = "https://gw.open.icbc.com.cn/ui/jft/ui/user/entrustopenacct/submit/V1";
//    private static final String AES_Key = "nuCVNzIxOTHZWv8YjEeYQA==";
//    private static final String CAMS_PUBLIC_KEY = "655CE8706E6ED9A30B92E57D8D645ADDE8C541C27C5C5AFD529C610C4C0B04F9074E3B6E933C50A3316AEA60CEF461BE4C7916D2AF51170D3A2631394A7F3939";
//    private static final String APIGW_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCMpjaWjngB4E3ATh+G1DVAmQnIpiPEFAEDqRfNGAVvvH35yDetqewKi0l7OEceTMN1C6NPym3zStvSoQayjYV+eIcZERkx31KhtFu9clZKgRTyPjdKMIth/wBtPKjL/5+PYalLdomM4ONthrPgnkN4x4R0+D4+EBpXo8gNiAFsNwIDAQAB";
//    private static final String OUT_VENDOR_ID = "071301";
//    private static final String PROJECT_ID = "PJ14001401B000160171";

	// 测试环境
	@Value("${hygf.icbc.appId}")
	private String APP_ID;
	@Value("${hygf.icbc.corpNo}")
	private String corpNo;
	@Value("${hygf.icbc.myPrivateKey}")
	private String MY_PRIVATE_KEY;
	@Value("${hygf.icbc.serviceUrl}")
	private String serviceUrl;
	@Value("${hygf.icbc.aesKey}")
	private String AES_Key;
	@Value("${hygf.icbc.camsPublicKey}")
	private String CAMS_PUBLIC_KEY;
	@Value("${hygf.icbc.apigwPublicKey}")
	private String APIGW_PUBLIC_KEY;
	@Value("${hygf.icbc.outVendorId}")
	private String OUT_VENDOR_ID;
	@Value("${hygf.icbc.projectId}")
	private String PROJECT_ID;
	/**
	 * 协议总限额
	 */
	@Value("${hygf.icbc.protocolLimitAmount:2500000000}")
	private String protocolLimitAmount;
	/**
	 * 单笔限额
	 */
	@Value("${hygf.icbc.trxLmtAmt:10000000}")
	private String trxLmtAmt;
	/**
	 * 日累计限额
	 */
	@Value("${hygf.icbc.dayLmtAmt:20000000}")
	private String dayLmtAmt;

	@Value("${hygf.icbc.loanTotalAmt:0}")
	private String loanTotalAmt;
	/**
	 * 合作方接收结果通知 URL
	 */
	@Value("${hygf.icbc.callbackUrl:}")
	private String callbackUrl;

	@Resource(type = PeasantHouseholdServiceImpl.class)
	private PeasantHouseholdServiceImpl peasantHouseholdService;

	@Resource(type = HygfIcbcRecordMapper.class)
	private HygfIcbcRecordMapper hygfIcbcRecordMapper;

	@Resource(type = HouseholdContractMapper.class)
	private HouseholdContractMapper householdContractMapper;

	@Resource(type = PowerStationEngineeringInfoMapper.class)
	private PowerStationEngineeringInfoMapper powerStationEngineeringInfoMapper;

	@Resource(type = HygfIcbcRequestMapper.class)
	private HygfIcbcRequestMapper hygfIcbcRequestMapper;

	public void icbcRegisterWalletUrl(HttpServletRequest req, HttpServletResponse resp) {
		try {
			UiIcbcClient client = new UiIcbcClient(APP_ID, IcbcConstants.SIGN_TYPE_RSA2, MY_PRIVATE_KEY,
					IcbcConstants.CHARSET_UTF8);

			String userId = req.getParameter("userId");
//            String userId = "071301";

			JftUiUserEntrustopenacctSubmitRequestV1 request = new JftUiUserEntrustopenacctSubmitRequestV1();
			request.setServiceUrl(serviceUrl + "/ui/jft/ui/user/entrustopenacct/submit/V1");

			JftUiUserEntrustopenacctSubmitRequestV1.JftUiUserEntrustopenacctSubmitRequestV1Biz bizContent = new JftUiUserEntrustopenacctSubmitRequestV1.JftUiUserEntrustopenacctSubmitRequestV1Biz();
			bizContent.setAppId(APP_ID);
			bizContent.setCorpNo(corpNo);
			bizContent.setOutUserId(userId); // 用户唯一id
			bizContent.setCorpSerno(UUID.randomUUID().toString());
			bizContent.setTrxChannel(trxChannel);
			bizContent.setSignProtocol("1"); // 是否对接缴费代扣流程
			bizContent.setOutVendorId(OUT_VENDOR_ID); // 企业外系统编号
			bizContent.setProjectId(PROJECT_ID); // 缴费项目编号
			bizContent.setBusiCode(userId); // 缴费编号

			Calendar calendar = Calendar.getInstance();
			Date date = new Date();// 当前时间
			calendar.setTime(date);
			int year = 26;// 26年
			calendar.add(Calendar.YEAR, year);// 在年份增加
			Date newDate = calendar.getTime();
			SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
			String formattedDate = formatter.format(newDate);

			bizContent.setProtocolEndDate(formattedDate); // 协议到期日
			bizContent.setProtocolLimitAmount(protocolLimitAmount); // 协议累计额
			JSONObject templateParams = new JSONObject();
			templateParams.put("prtl_enddate", formattedDate);// 协议到期日
			templateParams.put("loan_total_amt", loanTotalAmt);// 贷款限额（单位：分）
			templateParams.put("trx_lmt_amt", trxLmtAmt);// 单笔限额（单位：分）
			templateParams.put("day_lmt_amt", dayLmtAmt);// 日累计限额（单位：分）
			bizContent.setTemplateParams(templateParams.toJSONString());
			bizContent.setCallbackUrl(callbackUrl);

			bizContent.setCamsPublicKey(CAMS_PUBLIC_KEY);
			request.setBizContent(bizContent);
			// 调用工行 SDK，生成自动提交表单，将用户跳转到收方入驻页面
			log.info("聚富通委托代扣签约同步开户页面接口V1, 入参 => {}", JSON.toJSONString(request));
			//添加上送日志存储
			HygfIcbcRequest hygfIcbcRequest = new HygfIcbcRequest();
			hygfIcbcRequest.setPhase("请求");
			hygfIcbcRequest.setContent(JSONObject.toJSONString(request));
			hygfIcbcRequest.setRecDate(new Date());	
			hygfIcbcRequestMapper.insert(hygfIcbcRequest);
			String form = client.buildPostForm(request);
			log.info("聚富通委托代扣签约同步开户页面接口V1, 响应 => {}", form);
			resp.setHeader("Content-Type", "text/html;charset=" + IcbcConstants.CHARSET_UTF8);
			PrintWriter out = resp.getWriter();
			out.write("<html>");
			out.write("<head>");
			out.write("<meta http-equiv=\"Content-Type\" content=\"text/html;charset=" + IcbcConstants.CHARSET_UTF8
					+ "\">");
			out.write("</head>");
			out.write("<body>");
			out.write(form);
			out.write("</body>");
			out.write("</html>");
		} catch (IcbcApiException e) {
			log.error("聚富通委托代扣签约同步开户页面接口V1, error => ", e);
			throw new BadRequest(e.getErrMsg());
		} catch (Exception e) {
			log.error("聚富通委托代扣签约同步开户页面接口V1, error => ", e);
			throw new RuntimeException(e.getMessage());
		}

	}

	public JftApiUserEntrustopenacctQueryResponseV1 getHygfIcbcWalletInfo(String userId) {
		DefaultIcbcClient client = new DefaultIcbcClient(APP_ID, IcbcConstants.SIGN_TYPE_RSA2, MY_PRIVATE_KEY,
				IcbcConstants.CHARSET_UTF8, IcbcConstants.FORMAT_JSON, APIGW_PUBLIC_KEY, IcbcConstants.ENCRYPT_TYPE_AES,
				AES_Key, "", "");

		JftApiUserEntrustopenacctQueryRequestV1 request = new JftApiUserEntrustopenacctQueryRequestV1();
		request.setServiceUrl(serviceUrl + "/api/jft/api/user/entrustopenacct/query/V1");
		JftApiUserEntrustopenacctQueryRequestV1.JftApiUserEntrustopenacctQueryRequestV1Biz bizContent = new JftApiUserEntrustopenacctQueryRequestV1.JftApiUserEntrustopenacctQueryRequestV1Biz();
		bizContent.setAppId(APP_ID);
		bizContent.setOutVendorId(OUT_VENDOR_ID);
		bizContent.setOutUserId(userId);
		bizContent.setProjectId(PROJECT_ID);
		bizContent.setBusiCode(userId);
		request.setBizContent(bizContent);
		JftApiUserEntrustopenacctQueryResponseV1 response;
		try {
			log.info("聚富通委托代扣签约同步开户结果查询数据接口V1, => 入参: {}", JSON.toJSONString(request));
			response = client.execute(request, System.currentTimeMillis() + "");
			log.info("聚富通委托代扣签约同步开户结果查询数据接口V1, => 响应: {}", JSON.toJSONString(response));
			if (response.isSuccess()) {
				return response;
			} else {
				// 失败
				throw new BadRequest(response.getReturnMsg());
			}
		} catch (IcbcApiException e) {
			e.printStackTrace();
			log.error("聚富通委托代扣签约同步开户结果查询数据接口V1 error => ", e);
			throw new BadRequest(e.getErrMsg());
		} catch (Exception e) {
			e.printStackTrace();
			log.error("聚富通委托代扣签约同步开户结果查询数据接口V1 error => ", e);
			throw new RuntimeException(e.getMessage());
		}
	}

	/**
	 * 户用光伏开户签约异步通知使用
	 *
	 * @param request  request
	 * @param response response
	 * @return {@link Object}
	 * @throws @author yangyang
	 * @date 2024/7/18 20:15
	 */
	public Object registerWalletCallback(HttpServletRequest request, HttpServletResponse response) throws Exception {
		log.info("户用光伏开户签约异步通知, => 验签");
		String returnJson;
		// 网关公钥
		Map<String, String> params = new HashMap<>();
		String api = request.getParameter("api");
		String from = request.getParameter("from");
		String app_id = request.getParameter("app_id");
		String charset = request.getParameter("charset");
		String format = request.getParameter("format");
		String encrypt_type = request.getParameter("encrypt_type");
		String timestamp = request.getParameter("timestamp");
		String biz_content = request.getParameter("biz_content");
		String sign_type = request.getParameter("sign_type");
		String sign = request.getParameter("sign");
		params.put("from", from);
		params.put("api", api);
		params.put("app_id", app_id);
		params.put("charset", charset);
		params.put("format", format);
		params.put("encrypt_type", encrypt_type);
		params.put("timestamp", timestamp);
		// params.put("biz_content",
		// "{\"busiCode\":\"11098243\",\"return_msg\":\"success\",\"outUserId\":\"11098243\",\"custName\":\"5p2O5Y2r5Lic\",\"marketingStaffId\":\"\",\"newPayAcc\":\"NjIxNDc2MTUwMjYwMjc5MDc4OQ==\",\"signEntrsutPrtlSucceedFlag\":\"1\",\"certNo\":\"MjI5MDA1MTk3MzEwMjUwMjFY\",\"appId\":\"11000000000000028870\",\"msg_id\":\"20240814190453416\",\"projectId\":\"PJ140014023565102203\",\"openAccoutSucceedFlag\":\"02\",\"return_code\":0}");
		params.put("biz_content", biz_content);
		params.put("sign_type", sign_type);// 目前上行网关签名暂时仅支持RSA
		params.put("sign", sign);
		HygfIcbcRequest hygfIcbcRequest = new HygfIcbcRequest();
		hygfIcbcRequest.setPhase("验签");
		hygfIcbcRequest.setContent(JSONObject.toJSONString(params));
		hygfIcbcRequest.setRecDate(new Date());
		hygfIcbcRequestMapper.insert(hygfIcbcRequest);
		try {
			boolean verifyFlag = verifySignData(request, "/hygf/icbc/notify");
			if (verifyFlag) {
				// 验签成功
				hygfIcbcRequest.setPhase("查询");
				hygfIcbcRequestMapper.updateById(hygfIcbcRequest);

				// String biz_content = request.getParameter("biz_content");
				String decode = URLDecoder.decode(biz_content, "utf-8");
				Map<String, String> data = JSONObject.parseObject(decode, Map.class);
				log.debug("解密后参数:{}", data);// 进行自己的处理,此处默认处理成功，返回通知方成功,return_code=0
				// 其中certNo、custName、newPayAcc字段进行了base64编码，可以调用示例代码中的base64Decode进行解码
				// String custName = base64Decode(data.get("custName"));
				String certNo = base64Decode(data.get("certNo"));
				String newPayAcc = base64Decode(data.get("newPayAcc"));
				String outUserId = data.get("outUserId");
				String projectId = data.get("projectId");
				String openAccoutSucceedFlag = data.get("openAccoutSucceedFlag");
				String signEntrsutPrtlSucceedFlag = data.get("signEntrsutPrtlSucceedFlag");
				JftApiUserEntrustopenacctQueryResponseV1 hygfIcbcWalletInfo = this.getHygfIcbcWalletInfo(outUserId);
				// region 保存数据
				HygfIcbcRecord hygfIcbcRecord = this.lambdaQuery().eq(HygfIcbcRecord::getAmosUserId, outUserId)
						.last(" limit 1").one();
				if (hygfIcbcRecord == null) {
					hygfIcbcRecord = new HygfIcbcRecord();
				}
				PeasantHousehold peasantHousehold = peasantHouseholdService.lambdaQuery()
						.select(PeasantHousehold::getTelephone).eq(PeasantHousehold::getAmosUserId, outUserId)
						.last("limit 1").one();
				hygfIcbcRecord.setPhone(peasantHousehold != null ? peasantHousehold.getTelephone() : "");
				hygfIcbcRecord.setMediumId(newPayAcc);
				hygfIcbcRecord.setProjectId(projectId);
				hygfIcbcRecord.setOpenAccountStatus(openAccoutSucceedFlag);
				hygfIcbcRecord.setSignEntrsutPrtlStatus(signEntrsutPrtlSucceedFlag);
				hygfIcbcRecord.setCustName(peasantHousehold.getOwnersName());
				hygfIcbcRecord.setIdCard(certNo);
				hygfIcbcRequest.setPhase("组装");
				hygfIcbcRequest.setException(data.get("custName") + " -> " + peasantHousehold.getOwnersName());
				hygfIcbcRequestMapper.updateById(hygfIcbcRequest);

				if (hygfIcbcWalletInfo != null) {
					hygfIcbcRecord.setCustName(hygfIcbcWalletInfo.getCustName());
					hygfIcbcRecord.setIdCard(hygfIcbcWalletInfo.getCertNo());
					hygfIcbcRecord.setProtocolStatus(hygfIcbcWalletInfo.getProtocolStatus());
					hygfIcbcRecord.setProtocolStartTime(hygfIcbcWalletInfo.getProtocolStartDate());
					hygfIcbcRecord.setProtocolEndTime(hygfIcbcWalletInfo.getProtocolEndDate());
					hygfIcbcRecord.setTrxLimitAmount(hygfIcbcWalletInfo.getTrxLimitAmount());
					hygfIcbcRecord.setDayLimitAmount(hygfIcbcWalletInfo.getDayLimitAmount());
					hygfIcbcRecord.setProtocolLimitAmount(hygfIcbcWalletInfo.getProtocolLimitAmount());
					hygfIcbcRecord.setAppId(hygfIcbcWalletInfo.getAppId());
					hygfIcbcRecord.setOutUserId(hygfIcbcWalletInfo.getOutUserId());
					hygfIcbcRecord.setOutVendorId(hygfIcbcWalletInfo.getOutVendorId());
				}
				// hygfIcbcRecord.setDiscardStatus();
				hygfIcbcRecord.setAmosUserId(outUserId);
				hygfIcbcRecord.setRecDate(new Date());

				hygfIcbcRequest.setPhase("入库");
				hygfIcbcRequestMapper.updateById(hygfIcbcRequest);

				this.saveOrUpdate(hygfIcbcRecord);
				// endregion
				String copReturnCode = "0";// 通知合作方接收成功的返回码，固定
				String copReturnMsg = "success";// 合作方的返回信息，固定

				hygfIcbcRequest.setPhase("加签返回");
				hygfIcbcRequestMapper.updateById(hygfIcbcRequest);
				returnJson = sign(request, copReturnCode, copReturnMsg);
				log.info("通知响应json结果：{}", returnJson);
				return returnJson;
			} else {// 验签失败
				hygfIcbcRequest.setPhase("验签失败");
				hygfIcbcRequestMapper.updateById(hygfIcbcRequest);

				String copReturnCode = "‐12345";
				String copReturnMsg = "icbc jft sign not pass.";
				returnJson = sign(request, copReturnCode, copReturnMsg);
				log.error("通知响应json结果：{}", returnJson);

			}
		} catch (Exception e) {
			log.error("户用光伏开户签约异步通知, => error:", e);

			hygfIcbcRequest.setException(JSONObject.toJSONString(e));

			hygfIcbcRequestMapper.updateById(hygfIcbcRequest);
			String copReturnCode = "‐1";
			String copReturnMsg = "icbc jft error";
			returnJson = sign(request, copReturnCode, copReturnMsg);
		}
		return returnJson;
	}

	public HygfIcbcRecordDTO getObject(String amosUserId) {
		HygfIcbcRecord hygfIcbcRecord = this.lambdaQuery().eq(HygfIcbcRecord::getAmosUserId, amosUserId).last("limit 1")
				.one();
		HygfIcbcRecordDTO hygfIcbcRecordDTO = new HygfIcbcRecordDTO();
		if (hygfIcbcRecord == null) {
			PeasantHousehold peasantHousehold = peasantHouseholdService.lambdaQuery()
					.select(PeasantHousehold::getTelephone, PeasantHousehold::getOwnersName,
							PeasantHousehold::getIdCard)
					.eq(PeasantHousehold::getAmosUserId, amosUserId).last("limit 1").one();

			hygfIcbcRecordDTO.setCustName(peasantHousehold.getOwnersName());
			hygfIcbcRecordDTO.setIdCard(peasantHousehold.getIdCard());
			hygfIcbcRecordDTO.setPhone(peasantHousehold.getTelephone());
			hygfIcbcRecordDTO.setOpenAccountStatus(IcbcEnum.OpenAccountState.INITIAL.getCode());
			hygfIcbcRecordDTO.setOpenAccountStatusName(IcbcEnum.OpenAccountState.getNameByCode(
					IcbcEnum.OpenAccountState.INITIAL.getCode(), IcbcEnum.OpenAccountState.INITIAL.getName()));
		} else if (IcbcEnum.OpenAccountState.FAIL.getCode().equals(hygfIcbcRecord.getOpenAccountStatus())) {
			Bean.toModel(hygfIcbcRecord, hygfIcbcRecordDTO);
			PeasantHousehold peasantHousehold = peasantHouseholdService.lambdaQuery()
					.select(PeasantHousehold::getTelephone, PeasantHousehold::getOwnersName,
							PeasantHousehold::getIdCard)
					.eq(PeasantHousehold::getAmosUserId, amosUserId).last("limit 1").one();

			hygfIcbcRecordDTO.setCustName(peasantHousehold.getOwnersName());
			hygfIcbcRecordDTO.setIdCard(peasantHousehold.getIdCard());
			hygfIcbcRecordDTO.setPhone(peasantHousehold.getTelephone());
			hygfIcbcRecordDTO.setOpenAccountStatusName(IcbcEnum.OpenAccountState.getNameByCode(
					hygfIcbcRecordDTO.getOpenAccountStatus(), IcbcEnum.OpenAccountState.INITIAL.getName()));
			hygfIcbcRecordDTO.setProtocolStatusName(
					IcbcEnum.ProtocolStatus.getNameByCode(hygfIcbcRecordDTO.getProtocolStatus(), ""));
		} else {
			Bean.toModel(hygfIcbcRecord, hygfIcbcRecordDTO);
			hygfIcbcRecordDTO.setOpenAccountStatusName(IcbcEnum.OpenAccountState.getNameByCode(
					hygfIcbcRecordDTO.getOpenAccountStatus(), IcbcEnum.OpenAccountState.INITIAL.getName()));
			hygfIcbcRecordDTO.setProtocolStatusName(
					IcbcEnum.ProtocolStatus.getNameByCode(hygfIcbcRecordDTO.getProtocolStatus(), ""));
		}
		List<String> amosUserIds = Arrays.asList(amosUserId);
		List<PeasantHousehold> peasantHouseholds = peasantHouseholdService.lambdaQuery()
				.in(PeasantHousehold::getAmosUserId, amosUserIds).list();
		Map<String, List<PeasantHousehold>> peasantHouseholdMap = peasantHouseholds.stream()
				.collect(Collectors.groupingBy(PeasantHousehold::getAmosUserId));// 根据农户 ID 分组
		List<PeasantHousehold> peasantHouseholdList = peasantHouseholdMap.get(amosUserId);

		if (peasantHouseholdList != null && peasantHouseholdList.size() > 0) {
			peasantHouseholdList.forEach(e -> {
				if (e.getSurveyInformationId() != null) {
					e.setScale(householdContractMapper.getHygfCommercialScale(e.getPeasantHouseholdNo()));
					e.setRealScale(powerStationEngineeringInfoMapper
							.getRealScaleByPeasantHouseholdNo(e.getPeasantHouseholdNo()));
				}
			});
		}

		hygfIcbcRecordDTO.setPeasantHouseholds(
				Bean.toModels(peasantHouseholdList, HygfIcbcRecordDTO.IcbcPeasantHousehold.class));
		return hygfIcbcRecordDTO;
	}

	public List<HygfIcbcRecordDTO> listObject(HygfIcbcRecordQueryDTO hygfIcbcRecordQueryDTO) {
		List<HygfIcbcRecordDTO> list = hygfIcbcRecordMapper.listObject(hygfIcbcRecordQueryDTO);
		return toModels(list);
	}

	public Map<String, Object> queryForPage(int current, int size, HygfIcbcRecordQueryDTO hygfIcbcRecordQueryDTO) {
		PageHelper.startPage(current, size);
		List<HygfIcbcRecordDTO> list = hygfIcbcRecordMapper.pageList(hygfIcbcRecordQueryDTO);
		double sum = list.stream().mapToDouble(HygfIcbcRecordDTO::getPaymentAmount).sum();


		PageInfo<HygfIcbcRecordDTO> page = new PageInfo(list);
		Page<HygfIcbcRecordDTO> pagenew = new Page<>();
		pagenew.setCurrent(current);
		pagenew.setTotal(page.getTotal());
		pagenew.setSize(size);
		pagenew.setRecords(toModels(page.getList()));
		Map<String, Object> resultMap = Bean.BeantoMap(pagenew);
		resultMap.put("paymentAmountAll",sum);
		return resultMap;

//		======================================================統計錯誤=================================================================
//		// PageHelper.startPage(current, size);
//		Integer total = hygfIcbcRecordMapper.listObjectCount(hygfIcbcRecordQueryDTO);
//		hygfIcbcRecordQueryDTO.setLimit(size);
//		if (current == 1) {
//			hygfIcbcRecordQueryDTO.setOffset(0);
//		} else {
//			// int offset = (current - 1) * size > total ? : (current - 1) * size;
//			hygfIcbcRecordQueryDTO.setOffset((current - 1) * size);
//		}
//		List<HygfIcbcRecordDTO> list = hygfIcbcRecordMapper.listObject(hygfIcbcRecordQueryDTO);
//		Page<HygfIcbcRecordDTO> page = new Page<>();
//		page.setSize(size);
//		page.setCurrent(current);
//		page.setTotal(total);
//		page.setRecords(toModels(list));
//		return page;
	}

	private List<HygfIcbcRecordDTO> toModels(List<HygfIcbcRecordDTO> hygfIcbcRecords) {
		if (CollectionUtils.isEmpty(hygfIcbcRecords)) {
			return Collections.emptyList();
		}
		List<String> amosUserIds = hygfIcbcRecords.stream().map(HygfIcbcRecordDTO::getAmosUserId)
				.collect(Collectors.toList());
		List<PeasantHousehold> peasantHouseholds = peasantHouseholdService.lambdaQuery()
				.select(PeasantHousehold::getAmosUserId, PeasantHousehold::getRegionalCompaniesName,
						PeasantHousehold::getOwnersName, PeasantHousehold::getIdCard, PeasantHousehold::getTelephone)
				.in(PeasantHousehold::getAmosUserId, amosUserIds).list();
		Map<String, List<PeasantHousehold>> PeasantHouseholdMap = peasantHouseholds.stream()
				.collect(Collectors.groupingBy(PeasantHousehold::getAmosUserId));// 根据农户 ID 分组
		return hygfIcbcRecords.stream().map(hygfIcbcRecordDTO -> {
			hygfIcbcRecordDTO.setOpenAccountStatusName(IcbcEnum.OpenAccountState.getNameByCode(
					hygfIcbcRecordDTO.getOpenAccountStatus(), IcbcEnum.OpenAccountState.INITIAL.getName()));
			hygfIcbcRecordDTO.setProtocolStatusName(
					IcbcEnum.ProtocolStatus.getNameByCode(hygfIcbcRecordDTO.getProtocolStatus(), ""));
			List<PeasantHousehold> peasantHouseholdList = PeasantHouseholdMap.get(hygfIcbcRecordDTO.getAmosUserId());
//			if (IcbcEnum.OpenAccountState.FAIL.getCode().equals(hygfIcbcRecordDTO.getOpenAccountStatus())) {
//				hygfIcbcRecordDTO.setCustName(peasantHouseholds.get(0).getOwnersName());
//				hygfIcbcRecordDTO.setIdCard(peasantHouseholds.get(0).getIdCard());
//				hygfIcbcRecordDTO.setPhone(peasantHouseholds.get(0).getTelephone());
//			}
			if (!CollectionUtils.isEmpty(peasantHouseholdList)) {
				// 根据区域经销商名称去重
				List<HygfIcbcRecordDTO.IcbcPeasantHousehold> icbcPeasantHouseholds = Bean.toModels(peasantHouseholdList,
						HygfIcbcRecordDTO.IcbcPeasantHousehold.class);
				hygfIcbcRecordDTO.setPeasantHouseholds(icbcPeasantHouseholds.stream()
						.filter(distinctByKey(HygfIcbcRecordDTO.IcbcPeasantHousehold::getRegionalCompaniesName))
						.collect(Collectors.toList()));
			}
			return hygfIcbcRecordDTO;
		}).collect(Collectors.toList());
	}

	/**
	 * 验签方法
	 *
	 * @param request
	 * @param path
	 * @return
	 * @throws Exception
	 */
	private boolean verifySignData(HttpServletRequest request, String path) throws Exception {
		// 网关公钥
		Map<String, String> params = new HashMap<>();
		String api = request.getParameter("api");
		String from = request.getParameter("from");
		String app_id = request.getParameter("app_id");
		String charset = request.getParameter("charset");
		String format = request.getParameter("format");
		String encrypt_type = request.getParameter("encrypt_type");
		String timestamp = request.getParameter("timestamp");
		String biz_content = request.getParameter("biz_content");
		String sign_type = request.getParameter("sign_type");
		String sign = request.getParameter("sign");
		log.info(
				"户用光伏开户签约异步通知, 入参，from：[[{}]], api：[[{}]], app_id：[[{}]], charset：[[{}]], format：[[{}]], encrypt_type：[[{}]], timestamp：[[{}]], biz_content：[[{}]], sign_type：[[{}]], sign：[[{}]]",
				from, api, app_id, charset, format, encrypt_type);
		params.put("from", from);
		params.put("api", api);
		params.put("app_id", app_id);
		params.put("charset", charset);
		params.put("format", format);
		params.put("encrypt_type", encrypt_type);
		params.put("timestamp", timestamp);
		params.put("biz_content", biz_content);
		params.put("sign_type", sign_type);// 目前上行网关签名暂时仅支持RSA
		/********** 验证工行上行网关RSA签名 **********/
		String signStr = WebUtils.buildOrderedSignStr(path, params);
		log.info("验签入参，signStr：[[{}]], sign_type：[[{}]], APIGW_PUBLIC_KEY： [[{}]],charset：[[{}]],sign：[[{}]]", signStr,
				sign_type, APIGW_PUBLIC_KEY, charset, sign);
		boolean flag = IcbcSignature.verify(signStr, sign_type, APIGW_PUBLIC_KEY, charset, sign);
		log.info("验签结果：[[{}]]", flag);
		return flag;
	}

	/**
	 * 加签方法
	 *
	 * @param request
	 * @param copReturnCode
	 * @param copReturnMsg
	 * @return
	 * @throws Exception
	 */
	private String sign(HttpServletRequest request, String copReturnCode, String copReturnMsg) throws Exception {
		String msg_id = new SimpleDateFormat("yyyyMMdd").format(new Date())
				+ new SimpleDateFormat("HHmmss").format(new Date());
		String responseBizContent = "{\"return_code\":\"" + copReturnCode + "\",\"return_msg\":\"" + copReturnMsg + "\""
				+ ",\"msg_id\":\"" + msg_id + "\"}";
		String charset = request.getParameter("charset");// 调用过程使用的编码格式
		/**********
		 * 商户对消息返回响应进行签名，签名方式需与在API平台登记APP的sign_type保持一致(目前基本都是RSA2)
		 **********/
		// String signType = IcbcConstants.SIGN_TYPE_RSA2;
		String signType = IcbcConstants.SIGN_TYPE_RSA;
		String signStr = "\"response_biz_content\":" + responseBizContent + "," + "\"sign_type\":" + "\"" + signType
				+ "\"";
		String signParam = IcbcSignature.sign(signStr, signType, MY_PRIVATE_KEY, charset);
		String returnJson = "{\"response_biz_content\":" + responseBizContent + ",\"sign_type\":\"" + signType + "\""
				+ ",\"sign\":\"" + signParam + "\"}";
		return returnJson;
	}

	/**
	 * base64Decode
	 *
	 * @param str
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public String base64Decode(String str) throws UnsupportedEncodingException {
		if (str == null || "".equals(str)) {
			return "";
		}
		char[] ch = str.toCharArray();
		byte[] bt = Base64.getDecoder().decode(String.valueOf(ch));
		return new String(bt, "UTF-8");
	}

	public static <T> Predicate<T> distinctByKey(Function<? super T, Object> distinctField) {
		Map<Object, Boolean> distinctMap = new ConcurrentHashMap<>();
		return object -> distinctMap.putIfAbsent(distinctField.apply(object), Boolean.TRUE) == null;
	}

	public String repair(String userId) {
		JftApiUserEntrustopenacctQueryResponseV1 hygfIcbcWalletInfo = getHygfIcbcWalletInfo(userId);
		PeasantHousehold peasantHousehold = peasantHouseholdService.lambdaQuery().select(PeasantHousehold::getTelephone)
				.eq(PeasantHousehold::getAmosUserId, userId).last("limit 1").one();
		HygfIcbcRecord hygfIcbcRecord = this.lambdaQuery().eq(HygfIcbcRecord::getAmosUserId, userId).last(" limit 1")
				.one();
		if (hygfIcbcRecord == null) {
			hygfIcbcRecord = new HygfIcbcRecord();
		}
		if (hygfIcbcWalletInfo != null) {
			hygfIcbcRecord.setPhone(peasantHousehold != null ? peasantHousehold.getTelephone() : "");
			hygfIcbcRecord.setMediumId(hygfIcbcWalletInfo.getMediumId());
			hygfIcbcRecord.setProjectId("PJ140014023565102203");
			hygfIcbcRecord.setOpenAccountStatus(hygfIcbcWalletInfo.getOpenacctStatus());
			hygfIcbcRecord.setSignEntrsutPrtlStatus("1");
			hygfIcbcRecord.setCustName(hygfIcbcWalletInfo.getCustName());
			hygfIcbcRecord.setIdCard(hygfIcbcWalletInfo.getCertNo());
			hygfIcbcRecord.setProtocolStatus(hygfIcbcWalletInfo.getProtocolStatus());
			hygfIcbcRecord.setProtocolStartTime(hygfIcbcWalletInfo.getProtocolStartDate());
			hygfIcbcRecord.setProtocolEndTime(hygfIcbcWalletInfo.getProtocolEndDate());
			hygfIcbcRecord.setTrxLimitAmount(hygfIcbcWalletInfo.getTrxLimitAmount());
			hygfIcbcRecord.setDayLimitAmount(hygfIcbcWalletInfo.getDayLimitAmount());
			hygfIcbcRecord.setProtocolLimitAmount(hygfIcbcWalletInfo.getProtocolLimitAmount());
			hygfIcbcRecord.setAppId(hygfIcbcWalletInfo.getAppId());
			hygfIcbcRecord.setOutUserId(hygfIcbcWalletInfo.getOutUserId());
			hygfIcbcRecord.setOutVendorId(hygfIcbcWalletInfo.getOutVendorId());
		} else {
			return "开卡信息不存在";
		}
		// hygfIcbcRecord.setDiscardStatus();
		hygfIcbcRecord.setAmosUserId(userId);
		hygfIcbcRecord.setRecDate(new Date());

		this.saveOrUpdate(hygfIcbcRecord);

		return "success";
	}


  		public 	Map<String,Long> exportTotal(String developerCode, String regionalCompaniesCode, String province, String city, String district){

			List<HygfIcbcRecordExportDTO> dtos = hygfIcbcRecordMapper.exportTotal(developerCode, regionalCompaniesCode, province, city, district);
			Map<String, Long> collect = dtos.stream()
					.collect(Collectors.groupingBy(HygfIcbcRecordExportDTO::getOpenAccountStatus, Collectors.counting()));

			String[] strings = {"开户失败","开户成功","未开户"};
			List<String> names = Arrays.asList(strings);
			for (String name : names) {
				if (!collect.keySet().contains(name)) {
					collect.put(name,0L);
				}
			}


			// 根据 openAccountStatus 分组统计
			return collect;

		}

	public 	void exportData(HttpServletResponse response,String developerCode, String regionalCompaniesCode, String province, String city, String district){

		List<HygfIcbcRecordExportDTO> dtos = hygfIcbcRecordMapper.exportTotal(developerCode, regionalCompaniesCode, province, city, district);

		if (CollectionUtil.isNotEmpty(dtos)){
			ExcelUtil.createTemplate(response,"开卡统计","开卡统计",dtos, HygfIcbcRecordExportDTO.class,null,false);
		}

	}


	public void exportExcel(HttpServletResponse response, HygfIcbcRecordQueryDTO hygfIcbcRecordQueryDTO){
		List<HygfIcbcRecordExportDTO> hygfIcbcRecordExportDTOS = hygfIcbcRecordMapper.paymentAmountExport(hygfIcbcRecordQueryDTO);
		if (CollectionUtil.isNotEmpty(hygfIcbcRecordExportDTOS)){
			ExcelUtil.createTemplate(response,"聚富通信息","聚富通信息",hygfIcbcRecordExportDTOS, HygfIcbcRecordExportDTO.class,null,false);
		}
	}
}