package com.subscription.restful.web;

import java.io.BufferedReader;
import java.io.PrintWriter;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;

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

import org.apache.avalon.framework.ExceptionUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.cku.core.RESTResponse;
import com.cku.oa.finance.entity.PaymentOrder;
import com.cku.oa.finance.service.PaymentOrderService;
import com.cku.oa.finance.service.PaymentPayLogService;
import com.cku.restful.v1.finance.service.RestOrderService;
import com.cku.restful.v1.sys.model.WXPayResult;
import com.cku.restful.v1.sys.utils.JdomParseXmlUtils;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import com.subscription.restful.service.WXpayServiceImpl;
import com.subscription.restful.utils.MyWXPayConfig;
import com.thinkgem.jeesite.common.web.BaseController;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;

@Api(value = "公众号微信支付-xuxue", tags = { "公众号微信支付-xuxue" })
@RestController
@RequestMapping(value = "subscription")
public class WXController extends BaseController {

	@Autowired
	private WXpayServiceImpl wxpayServiceImpl;

	@Autowired
	private PaymentPayLogService paymentPayLogService;

	@Autowired
	private PaymentOrderService paymentOrderService;

	@Autowired
	private RestOrderService restOrderService;

	@Autowired
	private MyWXPayConfig wxPayConfig;

	/**
	 * 第一步、根据前端传入的URL生产签名数据，拉起支付使用
	 * 先通过code来获取AccessToken，再用AccessToken获取票据，票据获取成功后签名给前台，用来拉起支付
	 * 
	 * @param code
	 * @param request
	 * @return
	 * @throws Exception
	 */
	@ApiOperation(value = "（1）根据前端传入的URL生产签名数据，拉起支付使用", notes = "入参：\n" + "{\n" + "   \"url\":\"000857962\" \n" + "}\n")
	@ApiResponses(@ApiResponse(code = 200, message = "{\n" + " \"rc\": 0,\n" + "\"msg\": \"OK\",\n" + " \"data\": {\n"
			+ " \"appId\": \"wx254077ea0c1077dd\",\n" + " \"noncestr\": \"3ffb8b50007844d29680ad9449b19733\",\n"
			+ " \"timestamp\": \"1588041456\",\n" + " \"signature\": \"e6fcae3f6258c3d2041377591ea53f2a374e6851\"\n"
			+ " }\n" + "}\n" + ""))
	@RequestMapping(value = "getTicket", method = RequestMethod.POST)
	@ResponseBody
	public RESTResponse getTicket(@RequestBody String json, HttpServletRequest request) throws Exception {
		HashMap<String, String> map = JSON.parseObject(json, HashMap.class);
		String url = map.get("url");
		try {
			return new RESTResponse(wxpayServiceImpl.getTicket(url));
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return new RESTResponse(10001, e.getMessage());
		}

	}

	/**
	 * 第二步 新建微信付款单
	 * 
	 * @param json
	 * @param request
	 * @return
	 * @throws Exception
	 */
	@ApiOperation(value = "（2）新建微信付款单", notes = "入参：\n" + "{\n" + "\"orderId\":\"db0ebc31bc7f489eafae6e74f927e576\",\n"
			+ "\"openId\":\"oxAyL0-qeHJ9igGkaCltksl87_f8\"\n" + "}\n")
	@ApiResponses(@ApiResponse(code = 200, message = "{\n" + " \"rc\": 0,\n" + "\"msg\": \"OK\",\n" + " \"data\": {\n"
			+ " \"timeStamp\": \"1588041331\",\n"
			+ " \"package\": \"prepay_id=wx281035312710378552cf1c881463197800\",\n"
			+ " \"appId\": \"wx254077ea0c1077dd\",\n" + " \"sign\": \"44CD955D5D293BEB24DE16E9AE011116\",\n"
			+ " \"signType\":\"MD5\",\n" + " \"nonceStr\": \"0a7871b3602c47c2b10dbf4d8ba0a6ac\",\n"
			+ " \"timestamp\": \"1588041331\"\n" + " }\n" + "}\n"))
	@RequestMapping(value = "WXPay/create", method = RequestMethod.POST)
	@ResponseBody
	public RESTResponse createPayOrder(@RequestBody String json, HttpServletRequest request) throws Exception {
		HashMap<String, String> mapP = JSON.parseObject(json, HashMap.class);
		String orderId = mapP.get("orderId");
		String openId = mapP.get("openId");
		String userIp = getIpAddress(request);
		try {
			return wxpayServiceImpl.createPayOrder(orderId, userIp, openId);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			return new RESTResponse(10001, e.getMessage());
		}
	}

	/**
	 * 获取真实ip地址，避免获取代理ip
	 * 
	 * @throws UnknownHostException
	 */

	public String getIpAddress(HttpServletRequest request) throws UnknownHostException {

		String ip = request.getRemoteAddr();
		if (StringUtils.isBlank(ip)) {
			ip = "0:0:0:0:0:0:0:1";
		}
		return ip;
	}

	/**
	 * 第三步 查询付款结果
	 * 
	 * @param json
	 * @return
	 * @throws Exception
	 */
	@ApiOperation(value = "（3）查询付款结果", notes = "入参：\n" + "{\n" + "\"orderId\":\"db0ebc31bc7f489eafae6e74f927e576\"\n"
			+ "}")
	@ApiResponses(@ApiResponse(code = 200, message = "{\n" + " \"rc\": 0,\n" + "\"msg\": \"OK\",\n" + " \"data\": {\n"
			+ " \"result\": \"FAIL\" -- 支付SUCCESS 未支付FAIL\n" + " }\n" + "}"))
	@RequestMapping(value = "WXPay/check", method = RequestMethod.POST)
	public RESTResponse check(@RequestBody String json) throws Exception {
		logger.debug("~~~~~~~~~~~~~~~~前端调用1~~~~~~~~~" + json);
		HashMap<String, String> mapP = JSON.parseObject(json, HashMap.class);
		String orderId = mapP.get("orderId");
		RESTResponse response = wxpayServiceImpl.check(orderId);
		logger.debug("~~~~~~~~~~~~~~~~前端调用2~~~~~~~~~" + response);
		return response;
	}

	// @ApiIgnore
	@RequestMapping(value = "notifyUrlWeixin")
	public void notifySubscription(HttpServletRequest request, HttpServletResponse response) {

		Map<String, String> data = new HashMap<>(2);

		try {
			BufferedReader reader = request.getReader();
			String line = "";
			StringBuffer inputString = new StringBuffer();

			PrintWriter writer = response.getWriter();
			while ((line = reader.readLine()) != null) {
				inputString.append(line);
			}
			if (reader != null) {
				reader.close();
			}
			logger.info("----[微信回调]接收到的报文---" + inputString.toString());
			if (!StringUtils.isEmpty(inputString.toString())) {
				// 增加支付日志
				WXPayResult wxPayResult = JdomParseXmlUtils.getWXPayResult(inputString.toString());
				// 保存回调的支付日志
				paymentPayLogService.updatePayInfo(wxPayResult.getOut_trade_no(), wxPayResult.getTransaction_id(),
						inputString.toString());
				if ("SUCCESS".equalsIgnoreCase(wxPayResult.getReturn_code())) {
					WXPay wxpay = new WXPay(wxPayConfig);
					boolean result = wxpay.isPayResultNotifySignatureValid(WXPayUtil.xmlToMap(inputString.toString()));

					String orderId = wxPayResult.getOut_trade_no();
					try {
						if (result) {
							// 修改订单的状态
							PaymentOrder order = paymentOrderService.get(orderId);
							if (order != null && order.getPaymentState().equals("1")
									&& !StringUtils.isEmpty(order.getOrderCode())) {
								// 修改支付方式
								order.setPaymentWay("24");// 24代表微信支付
								order.setTransactionId(wxPayResult.getTransaction_id());
								// 会员端支付后处理逻辑
								restOrderService.afterPay(order);
								// 修改支付日志支付状态
								paymentPayLogService.updatePayState(orderId, "2", null);
							} else if (order != null && order.getPaymentState().equals("2")
									&& !StringUtils.isEmpty(order.getOrderCode())) {
								logger.info("用户支付成功，订单已经处理过");
							} else {
								logger.error("用户支付成功，但是处理失败，没有找到待处理订单");
								// 修改支付日志支付状态
								paymentPayLogService.updatePayState(orderId, "3", "用户支付成功，但是处理失败，没有找到待处理订单");
							}
							data.put("return_code", "SUCCESS");
							data.put("return_msg", "OK");

							writer.write(WXPayUtil.mapToXml(data));
						} else {
							data.put("return_code", "FAIL");
							writer.write(WXPayUtil.mapToXml(data));
							logger.error("---------微信支付验证签名失败----------");
							// 修改支付日志支付状态
							paymentPayLogService.updatePayState(orderId, "3", "验证签名失败");
						}
					} catch (Exception e) {
						// 修改支付日志支付状态
						paymentPayLogService.updatePayState(orderId, "3", ExceptionUtil.printStackTrace(e));
						logger.error("----微信支付处理失败---", e);
					}
				} else {
					data.put("return_code", "FAIL");
					writer.write(WXPayUtil.mapToXml(data));
					// 修改支付日志支付状态
					paymentPayLogService.updatePayState(wxPayResult.getOut_trade_no(), "3",
							"返回码错误：" + wxPayResult.getReturn_msg());
					logger.error("---------微信支付返回Fail----------" + wxPayResult.getReturn_msg());
				}
				if (writer != null) {
					writer.close();
				}
			} else {
				data.put("return_code", "FAIL");
				writer.write(WXPayUtil.mapToXml(data));
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

}
