package com.iamberry.wechat.handles.pay;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.StringReader;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

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

import com.iamberry.wechat.core.entity.ResultMsg;
import com.iamberry.wechat.core.entity.coupon.CouponItemDto;
import com.iamberry.wechat.core.entity.coupon.CouponType;
import com.iamberry.wechat.core.entity.eo.Promotions;
import com.iamberry.wechat.core.entity.ism.IntegralConfig;
import com.iamberry.wechat.core.entity.ism.IntegralLog;
import com.iamberry.wechat.core.entity.order.OrderItem;
import com.iamberry.wechat.face.coupon.CouponTypeService;
import com.iamberry.wechat.face.coupon.WelfareService;
import com.iamberry.wechat.face.ism.IntegralLogService;
import com.iamberry.wechat.service.ActivityUtil;
import com.iamberry.wechat.tools.ResultInfo;
import com.iamberry.wechat.tools.SendMessageUtil;
import com.iamberry.wechat.tools.StrUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.xml.sax.InputSource;

import com.iamberry.app.tool.log.RatFWLogger;
import com.iamberry.wechat.core.entity.coupon.CouponItem;
import com.iamberry.wechat.core.entity.drp.PlaceInfo;
import com.iamberry.wechat.core.entity.drp.PlaceOrder;
import com.iamberry.wechat.core.entity.member.CashLog;
import com.iamberry.wechat.core.entity.member.Member;
import com.iamberry.wechat.core.entity.mq.MQMessage;
import com.iamberry.wechat.core.entity.order.Order;
import com.iamberry.wechat.core.entity.wx.WxPayResult;
import com.iamberry.wechat.face.cart.CartService;
import com.iamberry.wechat.face.coupon.CouponItemService;
import com.iamberry.wechat.face.drp.PlaceInfoService;
import com.iamberry.wechat.face.drp.PlaceOrderService;
import com.iamberry.wechat.face.member.CashLogService;
import com.iamberry.wechat.face.member.MemberService;
import com.iamberry.wechat.face.order.AdminOrderService;
import com.iamberry.wechat.face.qrcode.QrcodeService;
import com.iamberry.wechat.face.reback.RebackServices;
import com.iamberry.wechat.handles.mq.MQServiceProxy;
import com.iamberry.wechat.tools.StaticInfo;

/**
 * @author 何秀刚
 * Class Description: 微信支付回调handler,所有的支付回调，都在本类完成
 * Create Date:2016年4月19日
 * Update Date:2016年4月19日
 */
@Controller
@RequestMapping("/callback")
public class ResponseWechatPayHandler {

	@Autowired
	private RatFWLogger ratFWLogger;
	
	private final Object lock = new Object();
	@Autowired
	private CartService cartService;
	@Autowired
	private PlaceOrderService placeOrderService;
	@Autowired
	private SendMessageUtil sendMessageUtil;
	@Autowired
	private AdminOrderService adminOrderService;
	@Autowired
	private MQServiceProxy mQservice;
	@Autowired
	private WelfareService welfareService;
	@Autowired
	CashLogService cashLogService;
	@Autowired
	CouponItemService couponItemService;
	@Autowired
	private IntegralLogService integralLogService;
	@Autowired
	private ActivityUtil activityUtil;
	@Autowired
	private MemberService memberService;
	@Autowired
	private CouponTypeService couponTypeService;

	/**
	 * 销售订单支付回调方法
	 */
	@SuppressWarnings("rawtypes")
	@RequestMapping("/orderPayBack")
	public void orderPayBack(HttpServletRequest request, 
			HttpServletResponse response) throws IOException {
		synchronized (lock) {
			String inputLine;
			StringBuilder notityXml = new StringBuilder();
			String resXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
			try {
				//获取XML参数
				while ((inputLine = request.getReader().readLine()) != null) {
					notityXml.append(inputLine);
				}
				request.getReader().close();
				// 解析XML格式的数据
				Map m = parseXmlToList2(notityXml.toString());
				WxPayResult wpr = new WxPayResult();
				wpr = setWxPayResultObj(wpr,m);
				// 判断微信返回的内容是否为SUCCESS
				assert "SUCCESS".equalsIgnoreCase(wpr.getResultCode());
				// 验证数据
				String orderIdMD5 = StaticInfo.orderIdMD5.decrypt(wpr.getAttach());
				assert orderIdMD5.equals(wpr.getOutTradeNo());
				// 组装数据
				Date nowDate = new Date();
				Order order = new Order();
				order.setSalesOrderid(orderIdMD5);
				order.setSalesStatus(2);
				order.setSalesTransactionId(wpr.getTransactionId());
				order.setSalesTransactionDate(nowDate);
				order.setSalesOpenid(wpr.getOpenid());
				Order or = adminOrderService.getShopOrderByOrderId(orderIdMD5);
				assert or.getSalesStatus() == 1;
				List<OrderItem> orderItemList = adminOrderService.getShopOrderItemByOrderId(or.getSalesOrderid());
				// 修改订单状态
				int count = cartService.updateOrderStatus(order);
				// 修改优惠券状态
				order=cartService.selectOrderInfoById(order);
				String couponId=order.getCouponId();
				if (couponId!=null && !"".equals(couponId)) {
					welfareService.useCoupon(wpr.getOpenid(), orderIdMD5, couponId);
				}

				//订单结算获取获取积分
				try{
					Integer configId = 2;		//日常 - 订单结算获取积分X*0.1
					Promotions promotions = activityUtil.getAllPromotions();
					if(promotions != null && promotions.getIntegralConfigList() !=null && promotions.getIntegralConfigList().size() > 0){
						List<IntegralConfig> integralConfigList = promotions.getIntegralConfigList();
						configId = integralConfigList.get(0).getInteConfId();
					}
					//获取积分
					Integer flag = integralLogService.addOrderChangIntegra(or.getSalesOrderid(),configId);
					if(flag < 1){
						ratFWLogger.info("订单获取积分失败，订单编号："+or.getSalesOrderid());
					}
				}catch (Exception e){
					ratFWLogger.info("error+订单获取积分失败，订单编号："+or.getSalesOrderid());
					e.printStackTrace();
				}

				assert count >= 1;
				// 给订单的回调修改状态
				{
					MQMessage message = new MQMessage();
					message.setServiceToMessage(orderIdMD5);
					message.setServiceOtherMessage(wpr.getTransactionId());
					message.setServiceIsSend(2);
					message.setServiceStatus(1);
					message.setServiceHandlerObjectName("cartServiceImpl");
					message.setServiceHandlerMethodName("supdateStateByOrderId");
					message.setServiceType(1);
					mQservice.insertMQMessage(message);
				}
				// 给RST推送信息
				{
					MQMessage message = new MQMessage();
					message.setServiceToMessage(orderIdMD5);
					message.setServiceOtherMessage("efast.trade.new.add");
					message.setServiceIsSend(2);
					message.setServiceStatus(1);
					message.setServiceType(1);
					message.setServiceHandlerObjectName("efastOrderServiceImpl");
					message.setServiceHandlerMethodName("addOrderInfoToEfast");
					mQservice.insertMQMessage(message);
				}
				//推送消息到微信
				{
					SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
					DecimalFormat df=new DecimalFormat("0.00");
					String payMoney = df.format((float)or.getSalesYetAmount()/100) + "元";
					sendMessageUtil.probationPaySuccess(
							ResultInfo.PAYSUCCESS,
							or.getSalesOrderid(),
							payMoney,
							"Aiberle微信商城",
							sdf.format(new Date()),
							ResultInfo.sendRemark1,
							order.getSalesOpenid(),
							ResultInfo.ORDER_DETAIL+order.getSalesOrderid());
				}
				BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
				out.write(resXml.getBytes());
				out.flush();
				out.close();
			} catch (Exception e) {
				BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
				out.write("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文有误]]></return_msg></xml>".getBytes());
				out.flush();
				out.close();
				LoggerFactory.getLogger(this.getClass()).error("", e);
			}
		}
	}
	
	
	/**
	 * 销售订单支付回调方法
	 */
	@SuppressWarnings("rawtypes")
	@RequestMapping("/drpPayBack")
	public void drpPayBack(HttpServletRequest request, 
			HttpServletResponse response) throws IOException {
		synchronized (lock) {
			String inputLine;
			String notityXml = "";
			String resXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
			try {
				//获取XML参数
				while ((inputLine = request.getReader().readLine()) != null) {
					notityXml += inputLine;
				}
				request.getReader().close();
				//解析XML格式的数据
				Map m = parseXmlToList2(notityXml);
				WxPayResult wpr = new WxPayResult();
				wpr=setWxPayResultObj(wpr,m);
				//判断
				if("SUCCESS".equalsIgnoreCase(wpr.getResultCode())){
					//resXml:返回给微信服务器的数据
					resXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
					String orderIdMD5 = StaticInfo.orderIdMD5.decrypt(wpr.getAttach());
					if (orderIdMD5.equals(wpr.getOutTradeNo())) {
						PlaceOrder placeOrder=new PlaceOrder();
						placeOrder.setId(orderIdMD5);
						placeOrder.setStatus(2); //已付款
						 int count = placeOrderService.UpdateOrder(placeOrder);
						if (count < 1) {
							resXml = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文有误]]></return_msg></xml>";
						}
					} else {
						resXml = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文有误]]></return_msg></xml>";
						ratFWLogger.error(this, "订单:" + orderIdMD5 + "支付成功，但是没有通过校验!");
					}
				}else{
					resXml = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml>";
				}
				BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
				out.write(resXml.getBytes());
				out.flush();
				out.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 解析xml片段为Map
	 * @param xml
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private Map parseXmlToList2(String xml) {
		Map retMap = new HashMap();
		try {
			StringReader read = new StringReader(xml);
			// 创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
			InputSource source = new InputSource(read);
			// 创建一个新的SAXBuilder
			SAXBuilder sb = new SAXBuilder();
			// 防止XXE
			sb.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
			sb.setFeature("http://xml.org/sax/features/external-general-entities", false);
			sb.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
			sb.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);

			// 通过输入源构造一个Document
			Document doc = (Document) sb.build(source);
			Element root = doc.getRootElement();// 指向根节点
			List<Element> es = root.getChildren();
			if (es != null && es.size() != 0) {
				for (Element element : es) {
					retMap.put(element.getName(), element.getValue());
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return retMap;
	}
    
	//封装参数
	public WxPayResult setWxPayResultObj(WxPayResult wpr ,Map m){
		//解析参数
		wpr.setAppid(m.get("appid").toString());
		wpr.setBankType(m.get("bank_type").toString());
		wpr.setCashFee(m.get("cash_fee").toString());
		wpr.setFeeType(m.get("fee_type").toString());
		wpr.setIsSubscribe(m.get("is_subscribe").toString());
		wpr.setMchId(m.get("mch_id").toString());
		wpr.setNonceStr(m.get("nonce_str").toString());
		wpr.setOpenid(m.get("openid").toString());
		wpr.setOutTradeNo(m.get("out_trade_no").toString());
		wpr.setAttach(m.get("attach").toString());
		wpr.setResultCode(m.get("result_code").toString());
		wpr.setReturnCode(m.get("return_code").toString());
		wpr.setSign(m.get("sign").toString());
		wpr.setTimeEnd(m.get("time_end").toString());
		wpr.setTotalFee(m.get("total_fee").toString());
		wpr.setTradeType(m.get("trade_type").toString());
		wpr.setTransactionId(m.get("transaction_id").toString());
		return wpr;
	}

	/**
	 * 测试订单推送
	 * @param orderId
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/test_order")
	public ResultMsg checkOrderPaySuccess(
			@RequestParam(value = "orderId") String orderId) {
		ResultMsg msg = new ResultMsg();

		String orderIdMD5 = orderId;
		Order or = adminOrderService.getShopOrderByOrderId(orderIdMD5);

		// 组装数据
		Date nowDate = new Date();
		Order order = new Order();
		order.setSalesOrderid(orderIdMD5);
		order.setSalesStatus(2);
		order.setSalesTransactionId("xxxxxxxxx");
		order.setSalesTransactionDate(nowDate);
		order.setSalesOpenid(or.getSalesOpenid());

		assert or.getSalesStatus() == 1;
		List<OrderItem> orderItemList = adminOrderService.getShopOrderItemByOrderId(or.getSalesOrderid());
		// 修改订单状态
		int count = cartService.updateOrderStatus(order);
		// 修改优惠券状态
		order=cartService.selectOrderInfoById(order);
		String couponId=order.getCouponId();
		if (couponId!=null && !"".equals(couponId)) {
			welfareService.useCoupon(or.getSalesOpenid(), orderIdMD5, couponId);
		}
		assert count >= 1;

		//订单结算获取获取积分
		try{
			Integer configId = 2;		//日常 - 订单结算获取积分X*0.1
			Promotions promotions = activityUtil.getAllPromotions();
			if(promotions != null && promotions.getIntegralConfigList() !=null && promotions.getIntegralConfigList().size() > 0){
				List<IntegralConfig> integralConfigList = promotions.getIntegralConfigList();
				configId = integralConfigList.get(0).getInteConfId();
			}
			//获取积分
			Integer flag = integralLogService.addOrderChangIntegra(or.getSalesOrderid(),configId);
			if(flag < 1){
				ratFWLogger.info("订单获取积分失败，订单编号："+or.getSalesOrderid());
			}
		}catch (Exception e){
			ratFWLogger.info("error+订单获取积分失败，订单编号："+or.getSalesOrderid());
			e.printStackTrace();
		}

		//推送消息到微信
		{
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			DecimalFormat df=new DecimalFormat("0.00");
			String payMoney = df.format((float)or.getSalesYetAmount()/100) + "元";
			sendMessageUtil.probationPaySuccess(
					ResultInfo.PAYSUCCESS,
					or.getSalesOrderid(),
					payMoney,
					"Aiberle微信商城",
					sdf.format(new Date()),
					ResultInfo.sendRemark1,
					order.getSalesOpenid(),
					ResultInfo.ORDER_DETAIL+order.getSalesOrderid());
		}
		return msg;
	}

}
