/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.ldt.shop.service.impl;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yeepay.yop.sdk.service.common.response.YopResponse;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springblade.common.cache.FlowCache;
import org.springblade.common.constant.CallbackServeUrl;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.flow.shop.task.WechatApplyTask;
import org.springblade.gateway.web_gateway.entity.vo.YeePayInfoVO;
import org.springblade.ldt.shop.dto.ArtificialAuthInfoData;
import org.springblade.ldt.shop.dto.ArtificialWechatApplyDto;
import org.springblade.ldt.shop.entity.Audit;
import org.springblade.ldt.shop.entity.Shop;
import org.springblade.ldt.shop.mapper.ShopMapper;
import org.springblade.ldt.shop.service.IAuditService;
import org.springblade.ldt.shop.service.IShopService;
import org.springblade.ldt.shop.vo.ShopVO;
import org.springblade.ldt.shop.vo.WechatConfigQueryVO;
import org.springblade.yeePay.common.YeePayConst;
import org.springblade.yeePay.common.YeepayApiConstant;
import org.springblade.yeePay.entity.saas.*;
import org.springblade.yeePay.service.YeepayCommonService;
import org.springblade.yeePay.service.YeepaySaasService;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;

import static org.springblade.common.enums.AppConstant.InvitationType.SHOP_INVITATION;
import static org.springblade.yeePay.common.YeepayApiConstant.businessRole.SETTLED_MERCHANT;

/**
 * 服务实现类
 *
 * @author BladeX
 * @since 2021-09-23
 */
@Slf4j
@Service
@AllArgsConstructor
public class ShopServiceImpl extends BaseServiceImpl<ShopMapper, Shop> implements IShopService {

	@Resource
	private ShopMapper shopMapper;

	private IAuditService auditService;
	private YeepayCommonService yeepayCommonService;
	private YeepaySaasService yeepaySaasService;
	private YeePayConst yeePayConst;

	@Override
	public IPage<ShopVO> selectShopPage(IPage<ShopVO> page, ShopVO shop) {
		return page.setRecords(baseMapper.selectShopPage(page, shop));
	}

	@Override
	public WechatApplyDto getAuthAuditInfo(String businessId) {
		Shop shop = shopMapper.selectById(businessId);
		Assert.notNull(shop.getMerchantNo(), "该商户没有易宝商户号");
		WechatApplyDto wechatApplyDto = WechatApplyDto.builder().build();
		wechatApplyDto.setSubMerchantNo(shop.getMerchantNo());
		wechatApplyDto.setRequestNo(IdUtil.simpleUUID());
		wechatApplyDto.setReportFee("XIANXIA");
		wechatApplyDto.setIdentificationType("IDENTIFICATION_TYPE_IDCARD");
		wechatApplyDto.setMicroBizType(YeepayApiConstant.microBizType.MICRO_TYPE_STORE.name());
		wechatApplyDto.setStoreAddressCode(shop.getLocationCode().split(",")[2]);
		String[] pics = shop.getShopPic().split(",");
		String storeHeaderCopy;
		String storeIndoorCopy;
		if (pics.length > 1) {
			storeHeaderCopy = pics[0];
			storeIndoorCopy = pics[1];
		} else if (pics.length == 1 && ObjectUtils.isNotEmpty(pics[0])) {
			storeHeaderCopy = pics[0];
			storeIndoorCopy = null;
		} else {
			storeHeaderCopy = null;
			storeIndoorCopy = null;
		}
		wechatApplyDto.setStoreHeaderCopy(storeHeaderCopy);
		wechatApplyDto.setStoreIndoorCopy(storeIndoorCopy);

		Audit audit = auditService.getOne(Wrappers.<Audit>lambdaQuery().eq(Audit::getEntityId, businessId));
		if (ObjectUtils.isNotEmpty(audit)) {
			wechatApplyDto.setStoreName(audit.getShopName());
			wechatApplyDto.setCompanyAddress(audit.getAddress());
			wechatApplyDto.setIdentificationBackCopy(audit.getIdCardContrary());
			wechatApplyDto.setIdentificationFrontCopy(audit.getIdCardFront());
			wechatApplyDto.setApplicantIdCard(audit.getLegalLicenceNo());
			wechatApplyDto.setApplicantName(audit.getLegalPerson());
			wechatApplyDto.setApplicantPhone(audit.getContactMobile());
			wechatApplyDto.setIdentificationValidDate(WechatApplyTask.transferDateForIdCard(audit.getValidDate()));
		}

		return wechatApplyDto;
	}

	@Override
	public String wechatApply(ArtificialWechatApplyDto artificialWechatApplyDto) {
		String identificationBackCopy = yeepayCommonService.addFileToYeepay(artificialWechatApplyDto.getIdentificationBackCopy());
		String identificationFrontCopy = yeepayCommonService.addFileToYeepay(artificialWechatApplyDto.getIdentificationFrontCopy());
		String storeHeaderCopy = yeepayCommonService.addFileToYeepay(artificialWechatApplyDto.getStoreHeaderCopy());
		String storeIndoorCopy = yeepayCommonService.addFileToYeepay(artificialWechatApplyDto.getStoreIndoorCopy());

		artificialWechatApplyDto.setRequestNo(IdUtil.simpleUUID());
		artificialWechatApplyDto.setIdentificationBackCopy(identificationBackCopy);
		artificialWechatApplyDto.setIdentificationFrontCopy(identificationFrontCopy);
		artificialWechatApplyDto.setStoreHeaderCopy(storeHeaderCopy);
		artificialWechatApplyDto.setStoreIndoorCopy(storeIndoorCopy);

		WechatApplyDto wechatApplyDto = BeanUtil.copyProperties(artificialWechatApplyDto, WechatApplyDto.class);
		YopResponse yopResponse = yeepaySaasService.wechatApply(wechatApplyDto);
		JSONObject res = JSON.parseObject(yopResponse.getStringResult());
		if (!Objects.equals(res.getString("returnCode"), "BMS00000")) {
			throw new ServiceException(res.getString("returnMsg"));
		}
		//队列信息封装
		ArtificialAuthInfoData authInfoData = ArtificialAuthInfoData.builder()
			.shopId(artificialWechatApplyDto.getShopId())
			.requestNo(res.getString("requestNo"))
			.applymentId(res.getString("applymentId"))
			.reportFee(artificialWechatApplyDto.getReportFee())
			.build();
		FlowCache.addArtificialAuthMember(authInfoData);
		return "申请成功";
	}

	@Override
	public String getAuthStateQuery(String businessId) {
		Shop shop = shopMapper.selectById(businessId);
		Assert.notNull(shop.getMerchantNo(), "该商户没有易宝商户号");
		YopResponse yopResponse = yeepaySaasService.authStateQuery(AuthStateQueryDto.builder().merchantNo(shop.getMerchantNo()).build());
		JSONObject res = JSON.parseObject(yopResponse.getStringResult());
		if (!Objects.equals(res.getString("returnCode"), "NIG00000")) {
			throw new ServiceException(res.getString("returnMsg"));
		}
		return res.getString("identityAuthDtos");
	}

	@Override
	public YeePayInfoVO getMerchantInfo(Long shopId) {
		Shop shop = shopMapper.selectById(shopId);
		if (ObjectUtils.isEmpty(shop.getMerchantNo())) {
			return YeePayInfoVO.builder().build();
		}
		YopResponse yopResponse = yeepaySaasService.accountInfosQuery(shop.getMerchantNo());
		JSONObject res = JSON.parseObject(yopResponse.getStringResult());
		if (!Objects.equals(res.getString("returnCode"), "UA00000")) {
			throw new ServiceException(res.getString("returnMsg"));
		}
		return YeePayInfoVO.builder()
			.shop(shop)
			.yeePayInfo(res)
			.build();
	}

	@SneakyThrows
	@Override
	public R<List<WechatConfigQueryVO>> getWechatConfigQuery(String businessId) {
		Shop shop = shopMapper.selectById(businessId);
		Assert.notNull(shop.getMerchantNo(), "该商户没有易宝商户号");
		YopResponse yopResponse = yeepaySaasService.wechatConfigQuery(
			WechatConfigQueryDto.builder()
				.parentMerchantNo(yeePayConst.getParentMerchantNo())
				.merchantNo(shop.getMerchantNo())
				/*.appIdType(YeepayApiConstant.appIdType.OFFICIAL_ACCOUNT)*/.build());
		JSONObject res = JSON.parseObject(yopResponse.getStringResult());
		if (!Objects.equals(res.getString("code"), "00000")) {
			throw new ServiceException(res.getString("message"));
		}
		String configResult = res.getString("configResult");
		if (StringUtils.isNotEmpty(configResult)) {
			return R.data(new ObjectMapper().readValue(res.getString("configResult"), new TypeReference<List<WechatConfigQueryVO>>() {
			}));
		} else {
			return R.data(Collections.emptyList());
		}
	}

	@Override
	public R wechatConfigAdd(WechatConfigAddDto wechatConfigAddDto) {
		Shop shop = shopMapper.selectById(wechatConfigAddDto.getMerchantNo());
		Assert.notNull(shop, "未找到该商户记录");
		wechatConfigAddDto.setMerchantNo(shop.getMerchantNo());
		wechatConfigAddDto.setParentMerchantNo(yeePayConst.getPlatformServiceNo());
		YopResponse yopResponse = yeepaySaasService.wechatConfigAdd(wechatConfigAddDto);
		JSONObject res = JSON.parseObject(yopResponse.getStringResult());
		if (!Objects.equals(res.getString("code"), "00000")) {
			throw new ServiceException(res.getString("message"));
		}
		return R.success("配置成功！");
	}

	private BladeRedis bladeRedis;

	@Override
	public R inviteMicro(MicroInvitationDto microInvitationDto) {
		microInvitationDto.setParentMerchantNo(yeePayConst.getPlatformServiceNo());
		microInvitationDto.setBusinessRole(SETTLED_MERCHANT.name());
		microInvitationDto.getAccountInfo().setSettlementDirection(YeepayApiConstant.settlementDirection.BANKCARD.name());
		microInvitationDto.setRequestNo("ldt" + microInvitationDto.getMerchantCorporationInfo().getLegalLicenceNo() + "micro");
		microInvitationDto.setNotifyUrl(CallbackServeUrl.CALL_BACK_SERVE_URL + "/invitation/callback/" + SHOP_INVITATION);
		YopResponse yopResponse = yeepaySaasService.inviteMicro(microInvitationDto);
		JSONObject res = JSON.parseObject(yopResponse.getStringResult());
		if (!Objects.equals(res.getString("returnCode"), "NIG00000")) {
			throw new ServiceException(res.getString("returnMsg"));
		}
		bladeRedis.set("manual-micro-invitation", res);
		return R.data(res);
	}

	@Override
	public R inviteMerchant(InvitationDto invitationDto) {
		invitationDto.setParentMerchantNo(yeePayConst.getPlatformServiceNo());
		invitationDto.setBusinessRole(SETTLED_MERCHANT.name());
		invitationDto.getSettlementAccountInfo().setSettlementDirection(YeepayApiConstant.settlementDirection.ACCOUNT.name());
		invitationDto.setRequestNo("ldt" + invitationDto.getMerchantCorporationInfo().getLegalLicenceNo() + "invite");
		invitationDto.setNotifyUrl(CallbackServeUrl.CALL_BACK_SERVE_URL + "/invitation/callback/" + SHOP_INVITATION);
		YopResponse yopResponse = yeepaySaasService.inviteMerchant(invitationDto);
		JSONObject res = JSON.parseObject(yopResponse.getStringResult());
		if (!Objects.equals(res.getString("returnCode"), "NIG00000")) {
			throw new ServiceException(res.getString("returnMsg"));
		}
		bladeRedis.set("manual-micro-invitation", res);
		return R.data(res);
	}

	//@Scheduled(cron = "0 */1 * * * ?")
	private void queryStatus() {
		//查询当前微信认证队列各个状态
		Set<ArtificialAuthInfoData> authList = FlowCache.artificialAuthList();
		if (Objects.isNull(authList)) {
			log.info("暂无认证队列");
			return;
		}
		authList.parallelStream().forEach(item -> {
			Shop shop = shopMapper.selectById(item.getShopId());
			Assert.notNull(shop, "该商户没有易宝商户号");
			WechatAuthDto wechatAuthDto = new WechatAuthDto();
			wechatAuthDto.setApplymentId(item.getApplymentId());
			wechatAuthDto.setReportFee(YeepayApiConstant.reportFeeType.valueOf(item.getReportFee()));
			wechatAuthDto.setRequestNo(item.getRequestNo());
			wechatAuthDto.setSubMerchantNo(shop.getMerchantNo());
			YopResponse yopResponse = yeepaySaasService.wechatAuthQuery(wechatAuthDto);
			JSONObject resObj = JSON.parseObject(yopResponse.getStringResult());
			String applymentState = resObj.getString("applymentState");
			//状态为待用户验证
			/*if (Objects.equals(YeepayApiConstant.applymentState.APPLYMENT_STATE_WAITTING_FOR_CONFIRM_CONTACT.name(), applymentState)) {
				prepareForAuth(item, resObj);
			}

			//状态为驳回
			if (Objects.equals(YeepayApiConstant.applymentState.APPLYMENT_STATE_REJECTED.name(), applymentState)) {
				applyReject(item, resObj.getString("rejectReason"));
			}

			//状态为已完成认证
			if (Objects.equals(YeepayApiConstant.applymentState.APPLYMENT_STATE_PASSED.name(), applymentState)) {
				completeFlow(item);
			}*/
		});
	}
}
