package org.springblade.yeePay.listener;

import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springblade.common.constant.SystemConstant;
import org.springblade.common.utils.SerializableUtil;
import org.springblade.core.mp.support.Condition;
import org.springblade.modules.guosen.activity.entity.Activity;
import org.springblade.modules.guosen.activity.service.IActivityService;
import org.springblade.modules.guosen.agenter.entity.Agenter;
import org.springblade.modules.guosen.agenter.service.IAgenterService;
import org.springblade.modules.guosen.agentertype.entity.AgenterType;
import org.springblade.modules.guosen.agentertype.service.IAgenterTypeService;
import org.springblade.modules.guosen.billRecord.entity.BillRecord;
import org.springblade.modules.guosen.billRecord.service.IBillRecordService;
import org.springblade.modules.guosen.helpRecord.dto.HelpRecordDTO;
import org.springblade.modules.guosen.helpRecord.service.IHelpRecordService;
import org.springblade.modules.guosen.loginUser.entity.LoginUser;
import org.springblade.modules.guosen.loginUser.service.ILoginUserService;
import org.springblade.modules.guosen.ordercommission.entity.OrderCommission;
import org.springblade.modules.guosen.ordercommission.service.IOrderCommissionService;
import org.springblade.modules.guosen.pointsGoods.dto.ExchangeDTO;
import org.springblade.modules.guosen.pointsGoods.service.IPointsGoodsService;
import org.springblade.modules.guosen.production.entity.Production;
import org.springblade.modules.guosen.production.service.IProductionService;
import org.springblade.modules.guosen.useragenter.entity.UserAgenter;
import org.springblade.modules.guosen.useragenter.service.IUserAgenterService;
import org.springblade.yeePay.event.PayNotifyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

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

@Component
public class PayNotifyListener {

	@Resource
	private IBillRecordService billRecordService;

	@Resource
	private IOrderCommissionService orderCommissionService;

	@Resource
	private IUserAgenterService userAgenterService;

	@Resource
	private RedisTemplate<String, String> redisTemplate;

	@Resource
	private IAgenterTypeService agenterTypeService;

	@Resource
	private IAgenterService agenterService;

	@Resource
	private IActivityService activityService;

	@Resource
	private ILoginUserService loginUserService;

	@Resource
	private IProductionService productionService;

	@Resource
	private IHelpRecordService helpRecordService;

	@Resource
	private IPointsGoodsService pointsGoodsService;

	private static final String AGENTERTYPE_REDIS_PREFIX = "agentertype:";


	/**
	 * 	支付回调业务逻辑处理
	 * @param  payNotifyEvent 回调解密数据
	 * */
	@EventListener
	@Async
	public void onApplicationEvent(PayNotifyEvent payNotifyEvent) {
		System.out.println("==================================================================");
		JSONObject decryptData = payNotifyEvent.getDecryptData();
		//返回数据
//		{
//			"channelOrderId":"4200001122202107026714708759",
//			"orderId":"1625223889567",
//			"bankOrderId":"5908531301210702",
//			"paySuccessDate":"2021-07-02 19:04:55",
//			"channel":"WECHAT",
//			"payWay":"WECHAT_OFFIACCOUNT",
//			"uniqueOrderNo":"1013202107020000002383974179",
//			"orderAmount":"0.01",
//			"payAmount":"0.01",
//			"payerInfo":"{\"bankCardNo\":\"\",\"bankId\":\"CFT\",\"cardType\":\"CFT\",\"mobilePhoneNo\":\"\",\"userID\":\"o19581K7Nz5lUwsqaT10yTqOe1MI\"}",
//			"realPayAmount":"0.01",
//			"parentMerchantNo":"10086062555",
//			"merchantNo":"10086062555",
//			"status":"SUCCESS"
//		}

		String status = decryptData.getString("status");
		String orderId = decryptData.getString("orderId");
		BillRecord billRecord = billRecordService.getOne(Condition.getQueryWrapper(new BillRecord()).lambda()
			.eq(BillRecord::getOrderId, orderId));
		Assert.notNull(billRecord, "支付记录中无此订单");
		if (billRecord.getPayStatus().equals(SystemConstant.BillRecordPayStatus.PAYED.getValue())) {
			return;
		}
		String channelOrderId = decryptData.getString("channelOrderId");
		String bankOrderId = decryptData.getString("bankOrderId");
		String channel = decryptData.getString("channel");
		String payWay = decryptData.getString("payWay");
		String uniqueOrderNo = decryptData.getString("uniqueOrderNo");
		String payAmount = decryptData.getString("payAmount");
		String payerInfo = decryptData.getString("payerInfo");
		String realPayAmount = decryptData.getString("realPayAmount");
		String parentMerchantNo = decryptData.getString("parentMerchantNo");
		String merchantNo = decryptData.getString("merchantNo");

		billRecord.setChannelOrderId(channelOrderId);
		billRecord.setBankOrderId(bankOrderId);
		billRecord.setChannel(channel);
		billRecord.setPayWay(payWay);
		billRecord.setUniqueOrderNo(uniqueOrderNo);
		billRecord.setPayAmount(payAmount);
		billRecord.setPayerInfo(payerInfo);
		billRecord.setRealPayAmount(realPayAmount);
		billRecord.setParentMerchantNo(parentMerchantNo);
		billRecord.setMerchantNo(merchantNo);
		billRecord.setYeePayStatus(status);

		Activity activity = activityService.getById(billRecord.getActivityId());
		LoginUser loginUser = loginUserService.getById(billRecord.getUserId());
		if (Objects.equals("SUCCESS", status)) {
			//支付成功
			String paySuccessDateStr = decryptData.getString("paySuccessDate");
			billRecord.setPaySuccessDate(paySuccessDateStr);
			billRecord.setPayStatus(1);//已付款
			//打赏
			this.handelSuccess(billRecord);
			//兑换商品
			if (billRecord.getType() == 3) {
				ExchangeDTO exchangeDTO = new ExchangeDTO();
				exchangeDTO.setCashValue(billRecord.getPrice());
				exchangeDTO.setUserId(billRecord.getUserId());
				exchangeDTO.setHotValue(billRecord.getHotValue());
				exchangeDTO.setPointsGoodsId(billRecord.getRelationId());
				exchangeDTO.setPointsValue(billRecord.getPointsValue());
				pointsGoodsService.exchange(exchangeDTO);
			}
			//分佣
			Long userId = billRecord.getUserId();
			List<UserAgenter> userAgenters = userAgenterService.getBaseMapper().selectList(new QueryWrapper<>(new UserAgenter())
				.lambda().eq(UserAgenter::getUserId, userId));
			if (userAgenters.size() > 0) {//需要分佣推广分红
				Long agenterId = userAgenters.get(0).getAgenterId();
				Agenter agenter = this.agenterService.getById(agenterId);
				OrderCommission orderCommission = new OrderCommission();
				orderCommission.setAgenterId(agenterId);
				orderCommission.setType(SystemConstant.CommissionType.RECOMMEND_COMMISSION.getValue());
				orderCommission.setOrderId(billRecord.getId());

				AgenterType agenterType = this.getCommissionRate(agenter);

				if(agenter.getEnabled() == 1) {//代理身份已启用
					orderCommission.setRate(agenterType.getRecommendRate());
					orderCommission.setAmt(orderCommission.getRate() != null ? billRecord.getPrice().multiply(activity.getGrossProfitRate()).multiply(agenterType.getRecommendRate()) : null);
					orderCommission.setStatus(SystemConstant.CommissionStatus.PAYING.getValue());

					orderCommissionService.save(orderCommission);
				}

			}

			//城市分红

			//获取城市代理的城市分红比例
			try {
				Agenter agenterSelect = new Agenter();
				agenterSelect.setLevel(Integer.valueOf(SystemConstant.AgenterType.CITY_AGENTER.getId().toString()));
				AgenterType cityAgenterType = this.getCommissionRate(agenterSelect);
				//获取用户所在城市的城市代理
				List<Agenter> agenters = agenterService.getBaseMapper().selectList(new QueryWrapper<>(new Agenter())
					.lambda().eq(Agenter::getLevel,SystemConstant.AgenterType.CITY_AGENTER.getId()).eq(Agenter::getProvince, loginUser.getProvince())
					.eq(Agenter::getCity, loginUser.getCity()).eq(Agenter::getEnabled, 1));

				for(Agenter agenter :agenters){
					if(agenter.getEnabled() == 1){
						OrderCommission cityOrderCommission = new OrderCommission();
						cityOrderCommission.setStatus(SystemConstant.CommissionStatus.PAYING.getValue());
						cityOrderCommission.setRate(cityAgenterType.getCityRate());
						//单笔价格*活动设置的毛利率*城市代理的分红比例
						cityOrderCommission.setAmt(billRecord.getPrice().multiply(activity.getGrossProfitRate()).multiply(cityAgenterType.getCityRate()));
						cityOrderCommission.setOrderId(billRecord.getId());
						cityOrderCommission.setType(SystemConstant.CommissionType.CITY_COMMISSION.getValue());
						cityOrderCommission.setAgenterId(agenter.getId());
						orderCommissionService.save(cityOrderCommission);
					}

				}
			}catch (Exception e){
				e.printStackTrace();
			}
		}else{
			//支付失败
			billRecord.setPayStatus(2);//取消支付
		}
		billRecordService.updateById(billRecord);
	}

	/**
	 * 打赏
	 * @param billRecord
	 */
	private void handelSuccess(BillRecord billRecord){
		HelpRecordDTO helpRecordDTO = new HelpRecordDTO();

		Long activityId = billRecord.getActivityId();
		Long userId = billRecord.getUserId();

		helpRecordDTO.setActivityId(activityId);
		helpRecordDTO.setSenderId(userId);

		Integer type = billRecord.getType();
		if (type == 1 || type == 2) {
			//作品打赏,作者打赏
			Long presentId = billRecord.getPresentId();
			Integer presentCount = billRecord.getPresentCount();
			Long relationId = billRecord.getRelationId();

			helpRecordDTO.setPresentId(presentId);
			helpRecordDTO.setCount(presentCount);
			if (type == 1) {
				//作品打赏
				//type 为1 时 relationId 等于 productId
				Production production = productionService.getById(relationId);
				Long id = production.getUserId();
				helpRecordDTO.setReceiverId(id);
				helpRecordDTO.setProductId(relationId);
				helpRecordDTO.setType(1);
			}else{
				//作者打赏
				//type 为2 时 relationId 等于 receiverId
				helpRecordDTO.setReceiverId(relationId);
				helpRecordDTO.setType(3);
			}
		}
		helpRecordService.doReward(helpRecordDTO);
	}

	/**
	 * 获取某个代理的代理类型详细
	 *
	 * @param agenter
	 * @return
	 */

	private AgenterType getCommissionRate(Agenter agenter) {
		AgenterType result = null;
		String agenterTypeString = redisTemplate.opsForValue().get(AGENTERTYPE_REDIS_PREFIX+agenter.getLevel().toString());
		try {
			if (agenterTypeString == null) {
				result = agenterTypeService.getById(agenter.getLevel());
				redisTemplate.opsForValue().set(AGENTERTYPE_REDIS_PREFIX+result.getId().toString(), SerializableUtil.serializeToString(result));
			} else {
				result = (AgenterType) SerializableUtil.deserializeToObject(agenterTypeString);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}
}
