package cn.pluss.platform.controller.home;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

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

import cn.pluss.platform.api.Result;
import cn.pluss.platform.api.ResultGenerator;
import cn.pluss.platform.constants.Constant;
import cn.pluss.platform.entity.*;
import cn.pluss.platform.exception.MsgException;
import cn.pluss.platform.merchantStore.MerchantStoreService;
import cn.pluss.platform.pay.ApiPayService;
import cn.pluss.platform.systemConfig.SystemConfigService;
import cn.pluss.platform.util.*;
import cn.pluss.platform.wap.MD5Util;
import cn.pluss.platform.wechat.WxConstants;
import cn.pluss.platform.wx.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.ModelAndView;
import cn.pluss.platform.deviceMerchantBuy.DeviceMerchantBuyService;
import cn.pluss.platform.wap.XmlUtil;
import cn.pluss.platform.leshua.LeshuaService;
import cn.pluss.platform.merchantMenber.MerchantMenberService;
import cn.pluss.platform.userApp.UserAppService;

/**
 * @author yuchen
 * 
 * @Description
 */
@Controller
@Slf4j
@RequestMapping("wechat")
public class WechantController {

	@Setter(onMethod_ = {@Autowired,@Lazy})
	private UserAppService userAppService;

	@Setter(onMethod_ = {@Autowired})
	private WxPayNotifyService wxPayNotifyService;

	@Setter(onMethod_ = {@Autowired})
	private LeshuaService leshuaService;

	@Setter(onMethod_ = {@Autowired})
	private DeviceMerchantBuyService deviceMerchantBuyService;

	@Setter(onMethod_ = {@Autowired})
	private  MerchantMenberService merchantMenberService;

	@Setter(onMethod_ = {@Autowired})
	private SystemConfigService systemConfigService;

	@Setter(onMethod_ = {@Autowired})
	private ApiPayService apiPayService;

	@Setter(onMethod_ = {@Autowired})
	private WxCommonService wxCommonService;

	@Setter(onMethod_ = {@Autowired})
	private MerchantStoreService merchantStoreService;

	@Setter(onMethod_ = {@Autowired})
	private RestTemplate restTemplate;

	/**
	 * 
	 * goUpgradePage:(跳转到升级页面). <br/>
	 * 
	 * 
	 * @author Administrator
	 * @param userId
	 * @return
	 * @since JDK 1.8
	 */
	@GetMapping(value = "/goUpgradePage")
	public ModelAndView goUpgradePage(String userId) {
		ModelAndView modelAndView = new ModelAndView();
		modelAndView.setViewName("wechat/goUpgradePage");
		setUpVipAmtResult(modelAndView,"twoUpVipAmount",2);
		setUpVipAmtResult(modelAndView,"threeUpVipAmount",3);
		modelAndView.addObject("userId", userId);
		UserApp userApp=new UserApp();
		userApp.setUserId(Long.valueOf(userId));
		userApp=userAppService.queryUserApp(userApp);
		if(null!=userApp) {
			modelAndView.addObject("level", userApp.getLevel());
		}
		return modelAndView;
	}

	public void setUpVipAmtResult(ModelAndView modelAndView, String propertyKey,int level) {
		String configValue = systemConfigService.querySystemConfigValue(propertyKey);
		if(StringUtil.isNotEmpty(configValue)){
			if(configValue.contains("-")){
				modelAndView.addObject(propertyKey, configValue.split("-")[0]);
				//modelAndView.addObject(shapeKey, propertyValue.split("-")[1]);
			}
		}else{
			if(level == 2){
				modelAndView.addObject(propertyKey, 999);
				//modelAndView.addObject(shapeKey, 500);
			}else{
				modelAndView.addObject(propertyKey, 9999);
				//modelAndView.addObject(shapeKey, 5000);
			}
		}
	}

	/**
	 * 
	 * jumpUrl:(乐刷支付完成后的跳转地址). <br/>
	 * 
	 * 
	 * @author Administrator
	 * @param orderNumber
	 * @param
	 * @return
	 * @since JDK 1.8
	 */
	@GetMapping("/jumpUrl")
	public ModelAndView jumpUrl(String orderNumber) {
		log.info("====订单号====" + orderNumber);
		if (orderNumber.contains("?")) {
			String str[] = orderNumber.split("[?]");
			orderNumber = str[0];
		}
		ModelAndView modelAndView = new ModelAndView();
		Map<String, String> reqMap = new HashMap<String, String>(16);
		Map<String, Object> mapLeshua = new HashMap<String, Object>(16);
		try {
			reqMap.put("service", "query_status");
			reqMap.put("merchant_id", ParametersUtil.LESHUALIU);
			reqMap.put("third_order_id", orderNumber);
			reqMap.put("nonce_str", StringUtil.getBillno());
			String requestPay = leshuaService.requestPay(reqMap, ParametersUtil.leshuapaykey, true);
			mapLeshua = XmlUtil.toMapLeshua(requestPay);
			String resp_code = (String) mapLeshua.get("resp_code");
			if ("0".equals(resp_code)) {
				String result_code = (String) mapLeshua.get("result_code");
				if ("0".equals(result_code)) {
					String status = (String) mapLeshua.get("status");
					if ("2".equals(status)) {
						modelAndView.setViewName("merchant/paySuccess");
					} else {
						modelAndView.setViewName("merchant/payFail");
					}
				} else {
					modelAndView.addObject("message", "支付结果查询错误");
					modelAndView.setViewName("merchant/error");
				}
			} else {
				modelAndView.addObject("message", "支付结果查询错误");
				modelAndView.setViewName("merchant/error");
			}
		} catch (Exception e) {
			e.printStackTrace();
			modelAndView.addObject("message", "支付结果查询错误");
			modelAndView.setViewName("merchant/error");
		}
		return modelAndView;
	}

//	public static Set<String> resExcludedSignParams() {
//		Set<String> exludedSignParams = new HashSet<String>(2);
//		exludedSignParams.add("sign");
//		exludedSignParams.add("error_code");
//		return exludedSignParams;
//	}

	/**
	 * 
	 * getMerchantInfo:(得到商户名称，门店名称). <br/>
	 * 
	 * 
	 * @author Administrator
	 * @param merchantCode
	 * @param storeId
	 * @return
	 * @since JDK 1.8
	 */
//	private MerchantStore getMerchantInfo(String merchantCode, String storeId) {
//		// 因害怕表数据有误 分别根据merchantCode 查商家表 storeId查门店表
//		MerchantStore merchantStore = new MerchantStore();
//		merchantStore.setStoreId(storeId);
//		MerchantBaseInfo merchantBaseInfo = new MerchantBaseInfo();
//		merchantBaseInfo.setMerchantCode(merchantCode);
//		List<MerchantBaseInfo> queryMerchantBaseInfoList = merchantBaseInfoService
//				.queryMerchantBaseInfoList(merchantBaseInfo);
//		if (queryMerchantBaseInfoList != null && queryMerchantBaseInfoList.size() > 0) {
//			merchantBaseInfo = queryMerchantBaseInfoList.get(0);
//			merchantStore.setMerchantCode(merchantCode);
//		} else {
//			merchantBaseInfo = null;
//			merchantStore = null;
//			return merchantStore;
//		}
//		List<MerchantStore> queryMerchantStoreList = merchantStoreService.queryMerchantStoreList(merchantStore);
//		if (queryMerchantStoreList != null && queryMerchantStoreList.size() > 0) {
//			merchantStore = queryMerchantStoreList.get(0);
//			merchantStore.setMerchantName(merchantBaseInfo.getMerchantName());
//		} else {
//			merchantStore = null;
//		}
//		return merchantStore;
//	}

	/**
	 * 从request中获取请求方IP
	 * 
	 * @param request
	 * @return
	 */
	public static String getIpAddress(HttpServletRequest request) {
		String ip = request.getHeader("x-forwarded-for");
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_CLIENT_IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_X_FORWARDED_FOR");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			// 若以上方式均为获取到ip则证明获得客户端并没有采用反向代理直接使用getRemoteAddr()获取客户端的ip地址
			ip = request.getRemoteAddr();
		}
		// 多个路由时，取第一个非unknown的ip
		final String[] arr = ip.split(",");
		for (final String str : arr) {
			if (!"unknown".equalsIgnoreCase(str)) {
				ip = str;
				break;
			}
		}
		return ip;
	}

	/**
	 * 
	 * wechatCallBack:(设备订单微信回调通知). <br/>
	 * 
	 * 
	 * @author Administrator
	 * @param request
	 * @param response
	 * @since JDK 1.8
	 */
	@PostMapping(value = "/wechatCallBack")
	public void wechatCallBack(HttpServletRequest request, HttpServletResponse response) {
		try {
			InputStream is = request.getInputStream();
			String xml = XmlUtil.toUTF8(is);
			Map<String, Object> notifyMap = XmlUtil.toMap(xml);// 将微信发的xml转map
			if ("SUCCESS".equals(notifyMap.get("result_code"))) {
				String ordersSn = (String) notifyMap.get("out_trade_no");// 商户订单号
				String transaction_id = (String) notifyMap.get("transaction_id");
				// String amountpaid = (String) notifyMap.get("total_fee");// 实际支付的订单金额:单位 分
				// String openid = (String) notifyMap.get("openid");// 用户openid
				String time_end = (String) notifyMap.get("time_end");// 支付完成时间
				// Double amount=Double.valueOf(amountpaid)*100;
				DeviceMerchantBuy deviceMerchantBuy = new DeviceMerchantBuy();
				deviceMerchantBuy.setOrderNo(ordersSn);
				deviceMerchantBuy = deviceMerchantBuyService.queryDeviceMerchantBuy(deviceMerchantBuy);
				if ("1".equals(deviceMerchantBuy.getStatus())) {
					response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>");
					return;
				}
				deviceMerchantBuy.setStatus("1");
				deviceMerchantBuy.setTransNo(transaction_id);
				SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
				deviceMerchantBuy.setTransDt(sdf.parse(time_end));
				deviceMerchantBuyService.updateDeviceMerchantBuy(deviceMerchantBuy);
			}
			is.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 *
	 * wechatCallBack:(设备订单微信回调通知). <br/>
	 *
	 * 
	 * @author Administrator
	 * @param request
	 * @param response
	 * @since JDK 1.8
	 */
	@PostMapping(value = "/wechatCallBackV2")
	public void wechatCallBackV2(HttpServletRequest request, HttpServletResponse response) {
		try {
			InputStream is = request.getInputStream();
			String xml = XmlUtil.toUTF8(is);
			is.close();
			// 将微信发的xml转map
			assert xml != null : "无有效参数";

			Map<String, Object> notifyMap = XmlUtil.toMap(xml);

			wxPayNotifyService.commonPayNotify(notifyMap);

			response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@RequestMapping("attentionCallBack")
	public void wechatNotice(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String signature = request.getParameter("signature");
		// 时间戳
		String timestamp = request.getParameter("timestamp");
		// 随机数
		String nonce = request.getParameter("nonce");
		// 随机字符串
		String echostr = request.getParameter("echostr");
		InputStream is = request.getInputStream();
		// 处理微信请求
		if (!StringUtil.isEmpty(echostr)) {
			// 响应消息
			PrintWriter out = response.getWriter();
			out.print(echostr);
			out.close();
			// this.sendMessages(echostr);
			response.setContentType("text/json; charset=utf-8");
			response.setCharacterEncoding("UTF-8");
			response.getWriter().print(echostr);
		}
		String xml = readRequestMsg(request);
		Map<String, Object> map = XmlUtil.toMap(xml);
		String MsgType = (String) map.get("MsgType");
		//openId
		String openId = (String) map.get("FromUserName");
		WxAccessTokenRequest tokenRequest = WxAccessTokenRequest.buidWxToken(ParametersUtil.APPID,ParametersUtil.APPSECRET,null, WxConstants.WX_USER_INFO_URL);
		log.info("【微信消息接收】解析消息内容为：{}", JSON.toJSONString(map));
		if("event".equals(MsgType)) {
			String eventKey = (String) map.get("EventKey");
			if("VIEW".equals(map.get("Event"))){
				request.getRequestDispatcher(eventKey).forward(request,response);
			}else if("subscribe".equals(map.get("Event"))||"SCAN".equals(map.get("Event"))){
				//关注公众号 消息回复
				if("subscribe".equals(map.get("Event"))){
					StringBuilder backMsgXml = new StringBuilder("<xml>");
					backMsgXml.append("<ToUserName><![CDATA["+openId+"]]></ToUserName>");
					backMsgXml.append("<FromUserName><![CDATA["+(String) map.get("ToUserName")+"]]></FromUserName>");
					backMsgXml.append("<CreateTime>"+System.currentTimeMillis()+"</CreateTime>");
					backMsgXml.append("<MsgType><![CDATA[text]]></MsgType>");
					backMsgXml.append("<Content><![CDATA[你好，欢迎关注收银呗生活圈！]]></Content>");
					backMsgXml.append("</xml>");
					response.setContentType("text/xml; charset=utf-8");
					response.setCharacterEncoding("UTF-8");
					response.getWriter().write(backMsgXml.toString());
				}
				WxUserInfoResponse wxUserInfo = wxCommonService.getWxUserInfo(tokenRequest, openId);
				if(StringUtil.isNotEmpty(eventKey)){
					eventKey = eventKey.replace("qrscene_","");
					String[] data = null;
					if(eventKey.contains("_")){
						data = eventKey.split("_");
					}else if(eventKey.contains(",")){
						data = eventKey.split(",");
					}else{
						MsgException.throwException("分隔符有误！");
					}
					//商户id
					String merchantCode = data[0];
					//门店id
					String storeId = data[1];
					//手机号
					String phone = data[2];
					MerchantMenber merchantMenber=new MerchantMenber();
					merchantMenber.setPhone(phone);
					merchantMenber.setStoreId(storeId);
					merchantMenber.setMerchantCode(merchantCode);
					List<MerchantMenber> queryMerchantMenberList = merchantMenberService.queryMerchantMenberList(merchantMenber);
					if(queryMerchantMenberList!=null&&queryMerchantMenberList.size()>0) {
						merchantMenber = queryMerchantMenberList.get(0);
						if(StringUtil.isBlank(merchantMenber.getOpenid())){
							merchantMenber.setOpenid(openId);
							if(wxUserInfo != null){
								wxUserInfo.buildMember(merchantMenber,null);
							}
							merchantMenberService.updateMerchantMenber(merchantMenber);
							try {
								MerchantStore store = merchantStoreService.getStoreByMerchantCode(merchantMenber.getMerchantCode());

								JSONObject miniprogram = new JSONObject();
								miniprogram.put("appid",ParametersUtil.APPLETS_APPID);
								miniprogram.put("pagepath","pages/card/index?storeId="+store.getId()+"&phone="+merchantMenber.getPhone());
								String first = "恭喜您成为本店会员，祝你生活愉快!";
								String remark = "如对此卡有疑问或查询会员更多优惠信息，可以点此进入小程序中查看！";
								double usableRechargeFee = merchantMenber.getUsableRechargeFee() == null ? 0 : StringUtil.bigDecimal(merchantMenber.getUsableRechargeFee());
								double usableGiveFee = merchantMenber.getUsableGiveFee() == null ? 0 : StringUtil.bigDecimal(merchantMenber.getUsableGiveFee());
								String useFee = BigDecimal.valueOf(usableRechargeFee + usableGiveFee).setScale(2,BigDecimal.ROUND_HALF_DOWN).toString();
								String[] array = {store.getStoreName(),merchantMenber.getPhone(),store.getStoreName()+"会员卡",useFee+"元"};
								WxTemolateRequest tempRequest = new WxTemolateRequest(openId,WxConstants.VIP_CARD_SUCCESS_TEMPLATE_ID,null,miniprogram)
										.buildData(first,remark,array);
								//发送开卡成功消息模板
								wxCommonService.sendTemplateMsg(tempRequest,tokenRequest);
							}catch (Exception e){
								e.printStackTrace();
							}
						}
					}
				}else{
					if(StringUtil.isNotEmpty(wxUserInfo.getUnionid())){
						merchantMenberService.updateByUnionId(openId,wxUserInfo.getUnionid());
					}
				}
			}
		}else{
			StringBuilder backMsgXml = new StringBuilder("<xml>");
			backMsgXml.append("<ToUserName><![CDATA["+openId+"]]></ToUserName>");
			backMsgXml.append("<FromUserName><![CDATA["+(String) map.get("ToUserName")+"]]></FromUserName>");
			backMsgXml.append("<CreateTime>"+System.currentTimeMillis()+"</CreateTime>");
			backMsgXml.append("<MsgType><![CDATA[text]]></MsgType>");
			backMsgXml.append("<Content><![CDATA[您好~很高兴为您服务\n<a href='https://gffhax2lhf4de.cschat.antcloud.com.cn/index.htm?tntInstId=1Jp_K9x2&scene=SCE00323632'>点此接入在线客服</a>]]></Content>");
			backMsgXml.append("</xml>");
			response.setContentType("text/xml; charset=utf-8");
			response.setCharacterEncoding("UTF-8");
			response.getWriter().write(backMsgXml.toString());
		}
	}
	/**
	 * 读取request数据
	 * 
	 * @param request
	 * @return
	 */
	public String readRequestMsg(HttpServletRequest request) {
		java.io.BufferedReader bis = null;
		String line = null;
		String result = "";
		try {
			bis = new java.io.BufferedReader(new java.io.InputStreamReader(request.getInputStream(), "UTF-8"));
			while ((line = bis.readLine()) != null) {
				result += line + "\r\n";
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				bis.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}

	@PostMapping("/orderPay")
	@ResponseBody
	public Result<Object> orderPay(@RequestBody JSONObject params) {
		String openid = params.getString("openid");
		String orderNumber = params.getString("orderNumber");
		return apiPayService.orderPay(openid,orderNumber);
	}

	@PostMapping("/getAddress")
	@ResponseBody
	public Result<Object> getAddress(String lat ,String lng) {
		String location = lat + "," + lng;
		String key = "5G5BZ-BXLC3-BRM32-3LPUU-HVBFF-ULBRS";
		String sercetKey = "LTDOFZ9utWc85jxPZdUzS2VelRCcqGf2";
		String method = "/ws/geocoder/v1";

		String reqParams = "key="+ key +"&location="+location + "&output=json";
		String signStr = method + "?"+reqParams + sercetKey;
		String sign = MD5Util.MD5Encode(signStr).toLowerCase(Locale.ROOT);
		String url = Constant.TENCENT_GET_ADDRESS_URL + "?" + reqParams + "&sig=" + sign;
		JSONObject response = restTemplate.getForObject(url, JSONObject.class);
		Integer status = response.getInteger("status");
		if(status != 0){
			return ResultGenerator.genFailResult(response.getString("message"));
		}
		JSONObject result = response.getJSONObject("result");
		JSONObject ad_info = result.getJSONObject("ad_info");
		String province = ad_info.getString("province");
		if(StringUtil.isEmpty(province)){
			province = ad_info.getString("city");
		}
		return ResultGenerator.genSuccessResult("获取成功",province);
	}
}
