package com.iamberry.rent.handlers.pay;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.StringReader;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.xml.sax.InputSource;

import com.iamberry.app.tool.log.RatFWLogger;
import com.iamberry.rent.face.machine.MachineService;
import com.iamberry.rent.face.order.RentOrderService;
import com.iamberry.rent.face.rebate.OrderRebateService;
import com.iamberry.rent.utils.SendMessageUtil;
import com.iamberry.wechat.core.entity.admin.ShopSystemRule;
import com.iamberry.wechat.core.entity.rent.RentOrder;
import com.iamberry.wechat.core.entity.rent.RentOrderItem;
import com.iamberry.wechat.core.entity.rent.RentTypeInfo;
import com.iamberry.wechat.core.entity.rent.ServiceCouponInfo;
import com.iamberry.wechat.core.entity.wx.WxPayResult;
import com.iamberry.wechat.face.admin.SystemService;
import com.iamberry.wechat.face.order.CodeService;
import com.iamberry.wechat.tools.ResultInfo;
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 RentPayHandler {
	@Autowired
	private RatFWLogger logger;
	@Autowired
	private RentOrderService rentOrderService;
	@Autowired
	private SendMessageUtil sendMessageUtil;
	@Autowired
	private CodeService codeService;
	@Autowired
	private OrderRebateService orderRebateService;
	@Autowired
	private SystemService systemService;
	@Autowired
	private MachineService machineService;
	
	/**
	 * 租赁订单支付回调方法
	 */
	@SuppressWarnings("rawtypes")
	@RequestMapping("/rentOrderPayBack")
	public synchronized void rentOrderPayBack(HttpServletRequest request, 
			HttpServletResponse response) throws IOException {
		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())) {
					// 组装数据
					RentOrder rentOrder = new RentOrder();
					rentOrder.setRentOrderId(orderIdMD5);
					rentOrder.setRentStatus(2);
					rentOrder.setRentOldStatus(1);
					rentOrder.setRentTransactionId(wpr.getTransactionId());// 微信支付ID
					rentOrder.setRentTransactionDate(new Date());// 微信支付时间
					rentOrder.setRentOpenid(wpr.getOpenid());
					
					RentOrderItem rentOrderItem = new RentOrderItem();
					rentOrderItem.setItemOrderId(orderIdMD5);
					rentOrderItem.setItemStatus(2);
					rentOrderItem.setItemInitCodeOldState(1);
					
					RentOrder order = rentOrderService.getRentOrderByOrderId(rentOrder);
					ServiceCouponInfo serviceCouponInfo = null;
					if (order.getRentServiceId() != null && !"".equals(order.getRentServiceId())) {
						serviceCouponInfo = new ServiceCouponInfo();
						serviceCouponInfo.setServiceId(order.getRentServiceId());
						serviceCouponInfo.setServiceOldStatus(2);
						serviceCouponInfo.setServiceStatus(3);
						serviceCouponInfo.setServiceOpenId(wpr.getOpenid());
					}
					// 修改订单状态和优惠券状态
					boolean flag = rentOrderService.updateOrderAndOrderItem(rentOrder, rentOrderItem, serviceCouponInfo);
					
					//根据id和状态查询租赁类型数据
					RentTypeInfo rentTypeInfo = new RentTypeInfo();
					rentTypeInfo.setTypeId(order.getRentTypeId());
					rentTypeInfo.setTypeStatus(1);
					rentTypeInfo = orderRebateService.getRebateType(rentTypeInfo);
					
					RentOrderItem orderItem = new RentOrderItem();
					List<RentOrderItem> itemList = rentOrderService.listOrderItem(orderItem);
					String productName = "";
					if (itemList != null && itemList.size() > 0) {
						for (RentOrderItem item : itemList) {
							if (item.getItemProductType() != null && item.getItemProductType().intValue() != 5) {
								productName = item.getItemProductName();
							}
						}
					}
					//获取租赁押金金额
					ShopSystemRule shopSystemRule =  systemService.selectOneShopRuleById(228);
					int deposit = shopSystemRule.getRuleNum().intValue();
					//支付成功后推送百胜
					try {
						rentOrderService.addRentOrderToEfast(orderIdMD5, wpr.getOpenid());
					} catch (Exception e) {
						e.printStackTrace();
						System.out.println("推送支付成功消息失败!");
					}
					
					//发送短信
					try{
						codeService.sendRentOrderToUser(order.getRentAddressTel(), 
								rentTypeInfo.getTypeDuration()/12, deposit/100, rentTypeInfo.getTypeServiceMoney()/100,order.getRentTypeId());
					} catch (Exception e) {
						logger.info("为订单-->" + order.getRentOrderId() + ",:" + "发送短信失败");
					}
					
					//推送消息到微信
					try {
						sendMessageUtil.probationPaySuccess(
								ResultInfo.PAYSUCCESS,
								order.getRentPayMoney()/100 + "元",
								productName,
								ResultInfo.PAYSUCCESSFOOT,
								order.getRentOpenid(),
								ResultInfo.RENT_ORDER_DETAIL);
					} catch (Exception e) {
						System.out.println("推送支付成功消息失败!");
					}
					
					if (!flag) {
						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>";
					logger.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();
			// 通过输入源构造一个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;
	}
	
	/**
     * 续费订单支付回调方法
     * @date 2017年3月23日09:33:28
     * @author muzx
     */
    @RequestMapping("/rent_recharge_order_pay_back")
    public synchronized void rentRechargeOrderPayBack(HttpServletRequest request, 
            HttpServletResponse response) throws IOException { 
        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())) {
                    if (machineService.rechargeOrderPayCallback(orderIdMD5, wpr.getTransactionId()) != 0) {
                        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>";
                    logger.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();
        }
	}
}
