package com.community.huiju.service.impl;

import com.community.commom.session.UserElement;
import com.community.huiju.common.wxpay.HfWxConfig;
import com.community.huiju.common.wxpay.WXPay;
import com.community.huiju.common.wxpay.WXPayConstants;
import com.community.huiju.common.wxpay.WXPayUtil;
import com.community.huiju.dao.*;
import com.community.huiju.model.*;
import com.community.huiju.service.WxPayServiceI;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * @author FXF
 * @date 2018-10-25
 */
@Service("wxPayService")
@Transactional(rollbackFor = Exception.class)
public class WxPayServiceImpl implements WxPayServiceI {
	private Logger log = LoggerFactory.getLogger(WxPayServiceImpl.class);
	
	@Autowired
	private TpBillInvoiceMapper tpBillInvoiceMapper;
	
	@Autowired
	private TpBillStatementMapper tpBillStatementMapper;

	@Autowired
	private TpBillMapper tpBillMapper;

	@Autowired
	private TaUserMapper taUserMapper;

	@Autowired
	private TaSysRoleMapper taSysRoleMapper;

	@Autowired
	private TpMessageMapper tpMessageMapper;

	@Autowired
	private TpBillOrderMapper tpBillOrderMapper;

	@Autowired
	private TaUserVerifyMapper taUserVerifyMapper;

	@Autowired
	private TpBuildingOwnerInfoMapper tpBuildingOwnerInfoMapper;

	/**
	 * 微信支付统一下单
	 *
	 * @return
	 * @param orderNo
	 * @param userElement
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Map<String, String> wxUnifiedOrder(String orderNo, UserElement userElement) throws Exception {
		HfWxConfig config = new HfWxConfig();
		WXPay wxpay = new WXPay(config);
		
		//获取支付金额
		List<TpBillOrder> billOrderList = tpBillOrderMapper.selectByOrderBumber(orderNo);
		if (CollectionUtils.isEmpty(billOrderList)){
			throw new Exception("订单不存在");
		}

		// 计算金额
		Integer payPrice = billOrderList.stream().mapToInt(e -> tpBillInvoiceMapper.selectByPrimaryKey(e.getTpBillInvoiceId()).getPayPrice()).sum();
		
		//下单
		Map<String, String> data = new HashMap<String, String>();
		data.put("body", "缴费");
		//商品号唯一
		data.put("out_trade_no", orderNo);
		data.put("device_info", "");
		data.put("fee_type", "CNY");
		//金额 后台计算
		data.put("total_fee", String.valueOf(payPrice));
		//终端IP
		data.put("spbill_create_ip", "123.12.12.123");
		//回调地址
		data.put("notify_url", "http://106.14.20.193:8086/app-api/wxNotify");
		// 此处指定为APP支付
		data.put("trade_type", "APP");
		Map<String, String> resp = wxpay.unifiedOrder(data);
		log.info("下单成功：{}", resp);
		if (resp.get("result_code").equalsIgnoreCase(WXPayConstants.FAIL)){
			throw new Exception(resp.get("err_code_des"));
		}
		//插入下单记录表
		
		//第二次重新生成签名
		Map<String, String> secondSignData = new HashMap<String, String>();
		long timestamp = Instant.now().getEpochSecond();
		secondSignData.put("appid", config.getAppID());
		secondSignData.put("partnerid", config.getMchID());
		secondSignData.put("prepayid", resp.get("prepay_id"));
		secondSignData.put("noncestr", resp.get("nonce_str"));
		secondSignData.put("timestamp", String.valueOf(timestamp));
		secondSignData.put("package", "Sign=WXPay");
		secondSignData.put("sign", WXPayUtil.generateSignature(secondSignData, config.getKey(), WXPayConstants.SignType.MD5));

		log.info("订单: {}， 状态变更为正在支付", orderNo);

		// 更改订单状态 为正在支付
		List<TpBillOrder> billOrders = tpBillOrderMapper.selectByOrderBumber(orderNo);
		billOrders.forEach(e-> {
			e.setOrderStatus("3");
			tpBillOrderMapper.updateByPrimaryKeySelective(e);
		});

		return secondSignData;
	}
	
	/**
	 * 支付成功的回调
	 *
	 * @return
	 * @param resultMap
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public String wxNotify(Map<String, String> resultMap) throws Exception {
		String outTradeNo = resultMap.get("out_trade_no");
		List<TpBillOrder> billOrderList = tpBillOrderMapper.selectByOrderBumber(outTradeNo);
		if (CollectionUtils.isEmpty(billOrderList)){
			return "不存在的订单";
		}

		// 缴费人在准备支付状态下更新, 这里是微信的回调所有没有 token

		for ( TpBillOrder billOrder : billOrderList){
			TpBillInvoice tpBillInvoice = tpBillInvoiceMapper.selectByPrimaryKey(billOrder.getTpBillInvoiceId());

			// 更新为正在支付状态
			// 更改收费单的 缴费时间, 修改人, 修改时间
			tpBillInvoice.setBillStatus("1");
			tpBillInvoice.setPayDate(new Date());
			tpBillInvoice.setUpdateDate(new Date());
			// 缴费方式  0：微信支付  1：线下缴费 2.支付宝支付
			tpBillInvoice.setPayType(resultMap.get("pay_type"));
			tpBillInvoiceMapper.updateByPrimaryKeySelective(tpBillInvoice);

			//插入流水账单表
			TpBillStatement tpBillStatement = new TpBillStatement();
			tpBillStatement.setBillInvoiceId(tpBillInvoice.getId());
			tpBillStatement.setCommunityId(tpBillInvoice.getCommunityId());
			tpBillStatement.setTaUserId(tpBillInvoice.getTaUserId());
			tpBillStatement.setPayPrice(tpBillInvoice.getPayPrice());
			tpBillStatement.setPayName(tpBillInvoice.getPayName());
			tpBillStatement.setPayRemark(tpBillInvoice.getBillName());
			tpBillStatement.setPayType(resultMap.get("pay_type"));
			tpBillStatement.setCreateTime(new Date());
			tpBillStatementMapper.insert(tpBillStatement);

			// 更新 收费单流水id
			tpBillInvoice.setBillStatementId(tpBillStatement.getId());
			tpBillInvoiceMapper.updateByPrimaryKeySelective(tpBillInvoice);

			// 更新收费组的 未交费用户数 和 已缴费用户数
			TpBill tpBill = tpBillMapper.selectByPrimaryKey(tpBillInvoice.getBillId());
			tpBill.setPayedNum(tpBill.getPayedNum() + 1);
			tpBill.setUnpayedNum(tpBill.getUnpayedNum() - 1);
			// 如果为零, 表示这个收费组收费完成
			if (tpBill.getUnpayedNum() <= 0) {
				tpBill.setBillStatus("1");
				tpBill.setUnpayedNum(0);
			}
			tpBillMapper.updateByPrimaryKeySelective(tpBill);

			// 把相对应的APP端, 代办消息设置为无效
//			Map<String, Object> map = Maps.newHashMap();
//			map.put("communityId", tpBillInvoice.getCommunityId());
//			map.put("billInvoiceId", tpBillInvoice.getId());
//			map.put("userId", tpBillInvoice.getTaUserId());
//			TpMessage tpMessage = tpMessageMapper.selectBillinvoiceMessage(map);
//			tpMessage.setStatus("0");
//			tpMessageMapper.updateByPrimaryKeySelective(tpMessage);
		}

		log.info("订单: {}， 状态变更为支付成功", outTradeNo);

		// 更改订单状态 为支付成功
		List<TpBillOrder> billOrders = tpBillOrderMapper.selectByOrderBumber(outTradeNo);
		billOrders.forEach(e-> {
			e.setOrderStatus("1");
			tpBillOrderMapper.updateByPrimaryKeySelective(e);
		});

		return "success";
	}
	
	/**
	 * 订单查询
	 *
	 * @return
	 */
	@Override
	public Map<String, String> wxOrderQuery(String outTradeNo) throws Exception {
		HfWxConfig config = new HfWxConfig();
		WXPay wxpay = new WXPay(config);
		
		Map<String, String> data = new HashMap<String, String>();
		data.put("out_trade_no", outTradeNo);
		return wxpay.orderQuery(data);
	}
	
	@Override
	@Transactional(rollbackFor = Exception.class)
	public String wxStartPay(List<Integer> billInvoiceIdArray, UserElement userElement) throws Exception {

		// 如果是家属/租客, 应该用业主的用户id
		TaUser taUser = taUserMapper.selectByPrimaryKey(userElement.getId());

		List<TpBillOrder> billOrderList = Lists.newArrayList();

		Random random = new Random();
		String orderNo = String.valueOf(System.currentTimeMillis()) + random.nextInt();

		/**
		 * 获取这个房产的业主
		 */

		TaUserVerify userVerify = taUserVerifyMapper.selectCommunityAndAddressAndRoleId(userElement.getCommunityId(),
				userElement.getPhaseId(), userElement.getBuildingId(), userElement.getUnitId(),
				userElement.getLevelId(), userElement.getRoomNoId());
		// 业主信息
		TaUser user = taUserMapper.selectByPrimaryKey(userVerify.getUserId());

		TpBuildingOwnerInfo tpBuildingOwnerInfo = tpBuildingOwnerInfoMapper.selectCommunityAndAddressAndPhone(userElement.getCommunityId(),
				userElement.getPhaseId(), userElement.getBuildingId(), userElement.getUnitId(),
				userElement.getLevelId(), userElement.getRoomNoId(), user.getLoginName());

		//获取支付金额
		for (Integer billInvoiceId : billInvoiceIdArray) {
			TpBillInvoice tpBillInvoice = tpBillInvoiceMapper.selectByIdAndBuildingOwnerInfoId(billInvoiceId,tpBuildingOwnerInfo.getId(),userElement.getCommunityId());
			if (null == tpBillInvoice){
				throw new Exception("订单不存在");
			}else if (!tpBillInvoice.getBillStatus().equals("0")){
				throw new Exception("正在支付的订单");
			}

			TpBillOrder tpBillOrder = new TpBillOrder();
			tpBillOrder.setCommunityId(userElement.getCommunityId());
			tpBillOrder.setTpBillId(tpBillInvoice.getBillId());
			tpBillOrder.setTpBillInvoiceId(tpBillInvoice.getId());
			tpBillOrder.setCreateDate(new Date());
			tpBillOrder.setCreateUser(userElement.getId());
			tpBillOrder.setUpdateDate(new Date());
			tpBillOrder.setUpdateUser(userElement.getId());
			tpBillOrder.setOrderBumber(orderNo);

			tpBillOrderMapper.insertSelective(tpBillOrder);

			// billOrderList.add(tpBillOrder);
		}

		// 修改缴费人
		// updateBillInvoiceBillStatus(billInvoiceIdArray, user.getUserName(), "1");

		// 生成缴费订单
		// tpBillOrderMapper.batchInsertSelective(billOrderList);

		return orderNo;
	}
	
	/**
	 * 取消支付
	 *
	 * @param outTradeNo
	 * @param userElement
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void wxCancelPay(String outTradeNo, UserElement userElement) throws Exception {

//		Integer userId = userElement.getId();
//
//		//获取支付金额
//		TpBillInvoice tpBillInvoice = tpBillInvoiceMapper.selectByIdAndUserId(billInvoiceId,userId,userElement.getCommunityId());
//		if (null == tpBillInvoice){
//			throw new Exception("订单不存在");
//		}else if (!tpBillInvoice.getBillStatus().equals("3")){
//			throw new Exception("不是正在支付的订单");
//		}
//		//更新为正在支付状态
//		updateBillInvoiceBillStatus(billInvoiceId,"0");



		//获取支付金额
		List<TpBillOrder> billOrderList = tpBillOrderMapper.selectByOrderBumber(outTradeNo);
		if (CollectionUtils.isEmpty(billOrderList)){
			throw new Exception("订单不存在");
		}

		List<TpBillInvoice> billInvoiceList = Lists.newArrayList();
		for (TpBillOrder tpBillOrder : billOrderList) {
			TpBillInvoice billInvoice = tpBillInvoiceMapper.selectByPrimaryKey(tpBillOrder.getTpBillInvoiceId());
			if (!billInvoice.getBillStatus().equals("3")){
				throw new Exception("不是正在支付的订单");
			}
			billInvoiceList.add(billInvoice);
		}

		// 缴费单id集合
		List<Integer> billInvoiceIdList = billInvoiceList.stream().map(e -> e.getId()).collect(Collectors.toList());

		//更新为正在支付状态
		updateBillInvoiceBillStatus(billInvoiceIdList,"0");
		log.info("订单: {}， 状态变更为取消支付", outTradeNo);

		// 更改订单状态 为支付成功
		List<TpBillOrder> billOrders = tpBillOrderMapper.selectByOrderBumber(outTradeNo);
		billOrders.forEach(e-> {
			e.setOrderStatus("0");
			tpBillOrderMapper.updateByPrimaryKeySelective(e);
		});
	}
	
	/**
	 * 更新支付状态
	 * @param billInvoiceIdList
	 * @param billStatus
	 */
	private void updateBillInvoiceBillStatus(List<Integer> billInvoiceIdList, String billStatus) {
		billInvoiceIdList.forEach(e -> {
			TpBillInvoice tpBillInvoiceUpdate = new TpBillInvoice();
			tpBillInvoiceUpdate.setBillStatus(billStatus);
			tpBillInvoiceUpdate.setId(e);
			tpBillInvoiceMapper.updateByPrimaryKeySelective(tpBillInvoiceUpdate);
		});

	}

	/**
	 * 更新支付状态
	 * @param billInvoiceIdList
	 * @param userName 缴费人
	 * @param billStatus
	 */
	private void updateBillInvoiceBillStatus(List<Integer> billInvoiceIdList, String userName, String billStatus) {
		billInvoiceIdList.forEach(e -> {
			TpBillInvoice tpBillInvoiceUpdate = new TpBillInvoice();
			tpBillInvoiceUpdate.setBillStatus(billStatus);
			tpBillInvoiceUpdate.setId(e);
			tpBillInvoiceUpdate.setPayName(userName);
			tpBillInvoiceMapper.updateByPrimaryKeySelective(tpBillInvoiceUpdate);
		});

	}
}
