package com.fjs.scenic.service.ord.impl;

import java.io.StringReader;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.fjs.scenic.cyt.request.NoticeOrderConsumedRequestBody;
import com.fjs.scenic.cyt.request.NoticeOrderRefundApproveResultRequestBody;
import com.fjs.scenic.cyt.request.Request;
import com.fjs.scenic.cyt.utils.AgentStandardExchangeJsonObject;
import com.fjs.scenic.cyt.utils.Base64Util;
import com.fjs.scenic.cyt.utils.JsonUtils;
import com.fjs.scenic.cyt.utils.Md5Utils;
import com.fjs.scenic.dto.OrderDetailModel;
import com.fjs.scenic.dto.OrdersDto;
import com.fjs.scenic.entity.good.Goods;
import com.fjs.scenic.entity.good.PriceRule;
import com.fjs.scenic.entity.good.StopTime;
import com.fjs.scenic.entity.order.ErrorOrder;
import com.fjs.scenic.entity.order.OrderDetails;
import com.fjs.scenic.entity.order.OrderNum;
import com.fjs.scenic.entity.order.Orders;
import com.fjs.scenic.entity.order.PlayMan;
import com.fjs.scenic.entity.user.LinkMan;
import com.fjs.scenic.mapper.good.GoodsMapper;
import com.fjs.scenic.mapper.good.PriceRuleMapper;
import com.fjs.scenic.mapper.good.StopTimeMapper;
import com.fjs.scenic.mapper.order.ErrorOrderMapper;
import com.fjs.scenic.mapper.order.OrderDetailsMapper;
import com.fjs.scenic.mapper.order.OrdersMapper;
import com.fjs.scenic.mapper.order.PlayManMapper;
import com.fjs.scenic.mapper.user.LinkManMapper;
import com.fjs.scenic.service.ord.ErrorOrderService;
import com.fjs.scenic.service.ord.OrdersService;
import com.fjs.scenic.service.ticket.OtaOrderService;
import com.fjs.scenic.service.ticket.TicketService;
import com.fjs.scenic.ticket.config.CytConfiguration;
import com.fjs.scenic.utils.Cons;
import com.fjs.scenic.utils.MessageByAli;
import com.fjs.scenic.utils.ReturnResult;
import com.fjs.scenic.utils.WXPayUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

/**
 * 订单 impl
 *
 * @author Administrator
 */
@Service
public class OrdersServiceImpl implements OrdersService {

	private Logger log = LoggerFactory.getLogger(this.getClass());

	@Autowired
	private OrdersMapper ordersMapper;
	@Autowired
	private OrderDetailsMapper orderDetailsMapper;
	@Autowired
	private GoodsMapper goodsMapper;
	@Autowired
	private PriceRuleMapper priceRuleMapper;
	@Autowired
	private LinkManMapper linkManMapper;
	@Autowired
	private PlayManMapper playManMapper;
	@Autowired
	private OtaOrderService otaOrderService;
	@Autowired
	private TicketService ticketService;
	@Autowired
	private ErrorOrderService errorOrderService;
	@Autowired
	protected CytConfiguration cytConfiguration;
	@Autowired
	private ErrorOrderMapper errorOrderMapper;
	@Autowired
	private RedisTemplate<String, Object> redisTemplate;
	@Autowired
	private HttpServletRequest request;
	@Autowired
	private StopTimeMapper stopTimeMapper;
	/*
	 * @Autowired private ScenicMapper scenicMapper;
	 */

	@Override
	public int insert(Orders record) {
		return ordersMapper.insert(record);
	}

	@Override
	public List<Orders> select(Orders record) {
		return ordersMapper.select(record);
	}

	@Override
	public int update(Orders record) {
		return ordersMapper.update(record);
	}

	@Override
	public void delete(Orders record) {
		ordersMapper.delete(record);
	}

	@Override
	public List<Orders> selectByParam(String field, String param) {
		Map<String, String> map = new HashMap<String, String>();
		map.put("field", field);
		map.put("param", param);
		return ordersMapper.selectByParam(map);
	}

	@Override
	public void updateByParam(String param) {
		Map<String, String> map = new HashMap<String, String>();
		map.put("param", param);
		ordersMapper.updateByParam(map);
	}

	@Override
	public void deleteByParam(String param) {
		Map<String, String> map = new HashMap<String, String>();
		map.put("param", param);
		ordersMapper.deleteByParam(map);
	}

	@Override
	public List<Orders> selectByJoin(String field, String param) {
		Map<String, String> map = new HashMap<String, String>();
		map.put("field", field);
		map.put("param", param);
		return ordersMapper.selectByJoin(map);
	}

	@Override
	public ReturnResult selectByStatus(Orders order, String type) {
		PageHelper.startPage(order.getPageNo(), order.getPageSize());
		/*
		 * Map<String, Object> param = new HashMap<>(); param.put("userId",
		 * order.getUserId()); param.put("type", type);
		 */
		List<Orders> list = ordersMapper.selectByStatus(order.getUserId(), type);
		PageInfo<Orders> page = new PageInfo<>(list);
		return ReturnResult.ok(page);
	}

	@Override
	public OrderDetailModel selectOrderDetail(Integer id, Integer userID) {
		return ordersMapper.selectOrderDetail(id, userID);
	}

	@Override
	public ReturnResult subOrder(Integer goodsId, Integer priceRuleId, Integer dateId, String parkingTime,
			String linkManIds, String buyUserName, String buyPhone, String buyIdCard, Double totelPrice, Double price,
			Integer num, Integer userId) {
		// TODO校验价格规则，
		log.info(
				"下单参数=====goodsId={}, priceRuleId={}, dateId={},parkingTime={}, linkManIds={}, buyUserName={}, buyPhone={}, buyIdCard={},totelPrice={}, price={}, num={},userId={}",
				goodsId, priceRuleId, dateId, parkingTime, linkManIds, buyUserName, buyPhone, buyIdCard, totelPrice,
				price, num, userId);
		if (StringUtils.isNotBlank(linkManIds)) {
			num = linkManIds.split(",").length;
		}
		PriceRule priceRule = null;
		if (null==priceRuleId) {
			priceRule = priceRuleMapper.selectPriceRulesByGoodsIdAndNowDate(goodsId);
			if(null==priceRule){
				return ReturnResult.error("当天不能购买此产品");
			}
		}
		ReturnResult r = validatePrice(goodsId, priceRuleId, dateId, parkingTime, linkManIds, buyUserName, buyPhone,
				buyIdCard, totelPrice, price, num, userId,priceRule);
		return r;
	}
	
	
	@Override
	public ReturnResult innerSubOrder(Integer goodsId,String linkManIds, String buyUserName, String buyPhone, String buyIdCard, Double totelPrice, Double price,Integer userId) {
		// TODO校验价格规则，
		if (StringUtils.isBlank(linkManIds)) {
			return ReturnResult.build(500, "游玩人不能为空");
		}
		int num = linkManIds.split(",").length;
		PriceRule priceRule = priceRuleMapper.selectPriceRulesByGoodsIdAndNowDate(goodsId);
		if(null==priceRule){
			return ReturnResult.error("当天不能购买此产品");
		}
		ReturnResult r = validatePrice(goodsId, priceRule.getId(), null, "", linkManIds, buyUserName, buyPhone,buyIdCard, totelPrice, price, num, userId,priceRule);
		return r;
	}
	
	

	private ReturnResult validatePrice(Integer goodsId, Integer priceRuleId, Integer dateId, String parkingTime,
			String linkManIds, String buyUserName, String buyPhone, String buyIdCard, Double totelPrice, Double price,
			Integer num, Integer userId,PriceRule priceRule) {
		if (StringUtils.isBlank(goodsId + "")) {
			return ReturnResult.build(500, "商品id不能为空");
		}
		/*if (StringUtils.isBlank(priceRuleId + "")) {
			return ReturnResult.build(500, "游玩时间不能为空");
		}*/
		/*if (StringUtils.isBlank(linkManIds)) {
			return ReturnResult.build(500, "游玩人不能为空");
		}*/
		if (StringUtils.isBlank(buyUserName)) {
			return ReturnResult.build(500, "预订人姓名不能为空");
		}
		if (StringUtils.isBlank(buyPhone)) {
			return ReturnResult.build(500, "预订人手机号不能为空");
		}
		/*if (StringUtils.isBlank(buyIdCard)) {
			return ReturnResult.build(500, "预定人身份证号不能为空");
		}*/
		if (totelPrice == null) {
			return ReturnResult.build(500, "总金额不能为空");
		}
		if (price == null) {
			return ReturnResult.build(500, "商品单价不能为空");
		}
		if (StringUtils.isBlank(num + "")) {
			return ReturnResult.build(500, "商品数量不能为空");
		}
		Goods goods = goodsMapper.selectByGoodsId(goodsId);
		if (goods == null) {
			return ReturnResult.build(500, "门票不存在");
		}
		if(goods.getSortType().equals("1")){
			List<StopTime> selectAll = stopTimeMapper.selectAll();
			if(null!=selectAll && selectAll.size()>=1){
				try {
					StopTime stopTime = selectAll.get(0);
					SimpleDateFormat df = new SimpleDateFormat("HH:mm");//设置日期格式
					String now = df.format(new Date());
					if(stopTime.getStartTime()!=null && stopTime.getEndTime()!=null){
						String[] startTime = stopTime.getStartTime().split(":");
						String[] endTime = stopTime.getEndTime().split(":");
						if(Integer.parseInt(startTime[0])>Integer.parseInt(endTime[0])){
							boolean boolen1 = hourMinuteBetween(now, stopTime.getStartTime(), "24:00");
							boolean boolen2 = hourMinuteBetween(now, "00:00", stopTime.getEndTime());
							if(boolen1 || boolen2){
								return ReturnResult.error(stopTime.getStartTime()+"至"+stopTime.getEndTime()+"停止售票");
							}
						}else{
							boolean boolen = hourMinuteBetween(now, stopTime.getStartTime(), stopTime.getEndTime());
							if(boolen){
								return ReturnResult.error(stopTime.getStartTime()+"至"+stopTime.getEndTime()+"停止售票");
							}
						}
					}else{
						log.error("开始时间或者结束时间为空导致不能售票");
						return ReturnResult.error("系统维护，停止售票");
					}
				}  catch (Exception e) {
					e.printStackTrace();
					log.error("日期转换异常");
					return ReturnResult.error("系统维护，停止售票");
				}
			}
		}
		
		Orders order = new Orders();
		order.setTotelPrice((int) (totelPrice * 100));
		order.setStatus(Cons.ORDER_STATUS.PAID);
		order.setOrderTime(new Date());
		order.setUserId(userId);
		if (dateId != null && StringUtils.isNotBlank(parkingTime)) {
			order.setDistTimeId(dateId);
			order.setParkingTime(parkingTime);
		}
		order.setPlayTime(new Date());// 更具价格规则id去查
		order.setBuyIdCard(buyIdCard);
		order.setBuyPhone(buyPhone);
		if(StringUtils.isNotBlank(buyUserName)){
			order.setBuyUserName(buyUserName);
		}
		/*String uuid = UUID.randomUUID().toString();
		//将 '-' 去掉
		uuid = uuid.replaceAll("-", "");
*/		SimpleDateFormat sdforder = new SimpleDateFormat("yyyyMMddHHmmssSSS");
		String ss = sdforder.format(new Date());
		order.setOrderNo(ss);
		//order.setOrderNo(SnowflakeIdWorker.generateId() + "");
		order.setNum(num);
		order.setOrderName(goods.getName());
		if(priceRule==null){
			if (StringUtils.isBlank(priceRuleId + "")) {
				return ReturnResult.build(500, "游玩时间不能为空");
			}
			priceRule = priceRuleMapper.selectByPrimaryKey(priceRuleId);
			if (priceRule == null) {
				return ReturnResult.build(500, "此日期门票不能购买");
			}
		}
		if(priceRule.getRepertory()<=0){
			return ReturnResult.build(500, "此日期门票不能购买");
		}
		order.setPlayTime(priceRule.getDate());
		if ((int) (price * 100) != priceRule.getSellPrice()) {
			return ReturnResult.build(500, "门票价格不正确");
		}

		/*
		 * boolean samedate = DateUtils.isSameDay(priceRule.getDate(), new
		 * Date()); if(samedate){ int stock = scenicMapper.getStock();
		 * if(stock<=0){ return ReturnResult.build(500, "手慢了库存不足"); } }
		 */
		// TODO总价

		// 保存游玩人
		List<PlayMan> playMans = new ArrayList<>();
		if(goods.getPersonType().equals("1")){
			if (StringUtils.isBlank(linkManIds)) {
				return ReturnResult.build(500, "游玩人不能为空");
			}
			String[] lmlds = linkManIds.split(",");
			for (int i = 0; i < lmlds.length; i++) {
				LinkMan linkman = linkManMapper.selectByPrimaryKey(Integer.parseInt(lmlds[i]));
				if (linkman == null) {
					return ReturnResult.build(500, "游玩人id不正确");
				} else {
					PlayMan playMan = new PlayMan();
					playMan.setIdCard(linkman.getIdCard());
					playMan.setName(linkman.getName());
					playMan.setOrderId(order.getId());
					playMans.add(playMan);
				}
			}
			if (playMans.isEmpty() || playMans.size() < 1) {
				return ReturnResult.build(500, "游玩人信息有误");
			}
		}
		log.info("开始提交订单，准备调用分销系统token={},time={}",request.getHeader(Cons.TOKEN.WECHAT),new Date());
		ReturnResult createOrder = ticketService.createOrder(order, playMans, goodsId + "", (int) (price * 100), num);
		log.info("开始提交订单，调用分销系统结束token={},time={}",request.getHeader(Cons.TOKEN.WECHAT),new Date());
		if (createOrder.getStatus() != 200) {
			log.error("调用分销系统出票失败");
			return createOrder;
		}
		/*
		 * if(samedate){ int stock = scenicMapper.subInventory(num);
		 * if(stock<=0){ log.error("扣库存失败"); } }
		 */
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		String format = sdf.format(priceRule.getDate());
		redisTemplate.delete("priceRule" + format+goods.getDoorType());
		// order 返回主键
		order.setDistOrderNo((String) createOrder.getData());
		int orderi = ordersMapper.insertSelective(order);
		if (orderi <= 0) {
			// TODO 分销系统创建订单成功，微信系统创建订单失败
			log.error("分销系统创建订单成功，微信系统创建订单失败orderno={},cytorderNo={}", order.getOrderNo(), order.getDistOrderNo());
			return ReturnResult.build(500, "网络异常请稍后再试");
		}
		// 订单详情
		OrderDetails orderDetails = new OrderDetails();
		orderDetails.setGoodsId(goodsId);
		orderDetails.setNum(num);
		orderDetails.setPrice((int) (price * 100));
		orderDetails.setOrderId(order.getId());
		int insertod = orderDetailsMapper.insert(orderDetails);
		if (insertod <= 0) {
			log.error("分销系统创建订单成功，微信系统创建订单详情失败orderno={},cytorderNo={}", order.getOrderNo(), order.getDistOrderNo());
			return ReturnResult.build(500, "网络异常请稍后再试");
		}
		for (PlayMan pm : playMans) {
			pm.setOrderId(order.getId());
			int insertpm = playManMapper.insertSelective(pm);
			if (insertpm <= 0) {
				log.error("分销系统创建订单成功，微信系统创建游玩人失败orderno={},cytorderNo={}", order.getOrderNo(), order.getDistOrderNo());
				return ReturnResult.build(500, "网络异常请稍后再试");
			}
		}

		if (order.getTotelPrice() == 0) {
			String orderNo = order.getOrderNo();
			order.setStatus(Cons.ORDER_STATUS.USED);
			order.setPayTime(new Date());
			ordersMapper.updateByPrimaryKeySelective(order);
			log.info("免费票修改订单状态后开始调用票务系统order={}", JSONObject.toJSONString(order));
			// 支付异步回掉后调用分销系统修改订单状态为已支付
			ReturnResult updateOrderToPayment = ticketService.updateOrderToPayment(order);
			if (updateOrderToPayment.getStatus() != 200) {
				// TODO 记录异常日志，支付回掉修改订单状态失败
				log.error("免费票修改订单状态成功，分销系统修改订单状态为已支付失败，需要通知用户退款，或系统手动退款");
				errorOrderService.inseterErrorOrder(orderNo, Cons.ERROR_ORDER_TYPE.OUT_TICKET,
						"免费订单修改订单状态成功，分销系统修改订单状态为已支付失败，需要通知用户退款，或系统手动退款");
				return ReturnResult.error("免费订单修改订单状态成功，分销系统修改订单状态为已支付失败。");
			}
		}
		/*String token = request.getHeader(Cons.TOKEN.WECHAT);
		redisTemplate.delete("code:" + token);*/
		log.info("提交订单结束token={},time={}",request.getHeader(Cons.TOKEN.WECHAT),new Date());
		return ReturnResult.ok(order.getId());
	}

	@Override
	public Orders selectByPrimaryKey(Integer id) {
		return ordersMapper.selectByPrimaryKey(id);
	}

	@Override
	public ReturnResult refundOrder(Integer id) {
		Orders order = ordersMapper.selectByPrimaryKey(id);
		if (order == null) {
			log.error("用户发起微信退款，无此订单orderid={}", id);
			return ReturnResult.build(500, "订单不存在");
		}
		if (order.getStatus().equals(Cons.ORDER_STATUS.USED) && order.getTotelPrice() != 0) {// 已付款出票中退款直接走微信退款
			DecimalFormat decimalFormat = new DecimalFormat("#");
			boolean b = WXPayUtil.refund(order.getOrderNo(), decimalFormat.format(order.getTotelPrice()),
					order.getOrderNo());
			if (b) {
				sendMessage(order.getDistOrderNo(),order.getBuyPhone());
				order.setStatus(Cons.ORDER_STATUS.REFUNDEDING);
				ordersMapper.updateByPrimaryKeySelective(order);
				return ReturnResult.ok();
			}
			return ReturnResult.build(500, "退款失败");
		} else if (order.getStatus().equals(Cons.ORDER_STATUS.TICKET)
				|| order.getStatus().equals(Cons.ORDER_STATUS.OVERDUE)
				|| order.getStatus().equals(Cons.ORDER_STATUS.REFUNDEDING)) {
			Integer ticketNum = orderDetailsMapper.getTicketNum(order.getId());
			if (ticketNum == null || ticketNum <= 0) {
				return ReturnResult.build(500, "门票数量不正确");
			}
			log.info("分销系统已出票订单申请退款order={}", JSONObject.toJSONString(order));
			ReturnResult refundTicket = ticketService.refundTicket(order, String.valueOf(ticketNum));
			if (refundTicket.getStatus() == 200) {
				sendMessage(order.getDistOrderNo(),order.getBuyPhone());
				Set<String> keys = redisTemplate.keys("priceRule:" + "*");
				redisTemplate.delete(keys);
				order.setStatus(Cons.ORDER_STATUS.REFUNDEDING);
				int i = ordersMapper.updateByPrimaryKeySelective(order);
				if (i < 0) {
					log.error("用户发起微信退款,修改订单状态失败，order={}", JSONObject.toJSONString(order));
					// 记录异常表
					/*
					 * ErrorOrder errorOrder = new ErrorOrder();
					 * errorOrder.setOrderId(order.getId());
					 * errorOrder.setOrderNo(order.getOrderNo());
					 * errorOrder.setDescription("畅游通退票成功，系统更新订单状态为退款中失败！");
					 * errorOrder.setTime(new Date());
					 * errorOrderMapper.insert(errorOrder);
					 */
					errorOrderService.inseterErrorOrder(order.getOrderNo(), Cons.ERROR_ORDER_TYPE.OUT_TICKET,
							"畅游通退票成功，系统更新订单状态为退款中失败！");
				}
			}
			return refundTicket;
		} else {
			return ReturnResult.build(500, "订单状态不正确");
		}
	}

	/**
	 * 通过订单号 掉分销的取消订单 腾出库存
	 *
	 * @param orderNo
	 * @return
	 */
	@Override
	public ReturnResult refundCytOrderByOrderNo(String orderNo) {
		Orders order = ordersMapper.selectByOrderNo(orderNo);
		if (order == null) {
			log.error("掉分销的取消订单，无此订单orderNo={}", orderNo);
			return ReturnResult.build(500, "订单不存在");
		}
		return refundCytOrderByOrder(order);
	}

	/**
	 * 通过订单 掉分销的取消订单 腾出库存
	 *
	 * @param order
	 * @return
	 */
	@Override
	public ReturnResult refundCytOrderByOrder(Orders order) {
		if (order.getStatus().equals(Cons.ORDER_STATUS.USED) && order.getTotelPrice() != 0) {// 已付款出票中退款直接走微信退款
			return ReturnResult.ok();
		} else if (order.getStatus().equals(Cons.ORDER_STATUS.TICKET)
				|| order.getStatus().equals(Cons.ORDER_STATUS.OVERDUE)
				|| order.getStatus().equals(Cons.ORDER_STATUS.REFUNDEDING)) {
			Integer ticketNum = orderDetailsMapper.getTicketNum(order.getId());
			if (ticketNum == null || ticketNum <= 0) {
				return ReturnResult.build(500, "门票数量不正确");
			}
			log.info("分销系统已出票订单申请退款order={}", JSONObject.toJSONString(order));
			ReturnResult refundTicket = ticketService.refundTicket(order, String.valueOf(ticketNum));
			return refundTicket;
		} else {
			return ReturnResult.build(500, "订单状态不正确");
		}
	}

	@Override
	public void pay(String orderNo, String cashFee) {
		log.info("微信成功支付回调OrdersServiceImpl-pay({}, {})", orderNo, cashFee);
		Orders order = ordersMapper.getOrderByOrderNo(orderNo);
		if(order == null){
			log.error("微信支付成功异步回掉修改订单状态,但订单不存在orderno={}", orderNo);
			return ;
		}
		if(order.getStatus().equals(Cons.ORDER_STATUS.CANCEL)){
			log.error("微信支付成功异步回掉修改订单状态,但订单为已取消，准备发起退款，order={}", JSONObject.toJSONString(order));
			DecimalFormat decimalFormat = new DecimalFormat("#");
			boolean b = WXPayUtil.refund(order.getOrderNo(), decimalFormat.format(order.getTotelPrice()),
					order.getOrderNo());
			if (b) {
				sendMessage(order.getDistOrderNo(),order.getBuyPhone());
				order.setStatus(Cons.ORDER_STATUS.REFUNDEDING);
				ordersMapper.updateByPrimaryKeySelective(order);
				return ;
			}
			log.error("微信支付成功异步回掉修改订单状态,但订单为已取消,退款失败，order={}", JSONObject.toJSONString(order));
			return ;
		}
		if(order.getStatus().equals(Cons.ORDER_STATUS.PAID)){
			order.setStatus(Cons.ORDER_STATUS.USED);
			order.setPayTime(new Date());
			int i = ordersMapper.updateByPrimaryKeySelective(order);
			if (i > 0) {
				log.info("微信支付异步回掉修改订单状态后开始调用票务系统order={}", JSONObject.toJSONString(order));
				// 支付异步回掉后调用分销系统修改订单状态为已支付
				ReturnResult updateOrderToPayment = ticketService.updateOrderToPayment(order);
				if (updateOrderToPayment.getStatus() != 200) {
					// TODO 记录异常日志，支付回掉修改订单状态失败
					log.error("微信支付异步回掉修改订单状态成功，分销系统修改订单状态为已支付失败，直接申请退款");
					errorOrderService.inseterErrorOrder(orderNo, Cons.ERROR_ORDER_TYPE.OUT_TICKET,
							"微信支付异步回掉修改订单状态成功，分销系统修改订单状态为已支付失败，直接申请退款");
					/*
					 * ReturnResult r = refundCytOrderByOrder(order);
					 * if(r.getStatus()!=200){ log.error(
					 * "支付成功修改订单状态为已支付成功，票务修改订单为已支付失败，准备自动退款失败，order={}",
					 * JSONObject.toJSONString(order)); }
					 */
					log.error("开始自动退款，order={}", JSONObject.toJSONString(order));
					DecimalFormat decimalFormat = new DecimalFormat("#");
					String b = WXPayUtil.refund(order.getOrderNo(), decimalFormat.format(order.getTotelPrice()));
					if ("true".equals(b)) {
						sendMessage(order.getDistOrderNo(),order.getBuyPhone());
						order.setStatus(Cons.ORDER_STATUS.REFUNDEDING);
						order.setPayTime(new Date());
						ordersMapper.updateByPrimaryKeySelective(order);
						log.info("pay>>>微信退款申请成功");
					} else if ("订单已全额退款".equals(b)) {
						log.info("pay>>>订单已全额退款");
					} else {
						log.error("pay>>>掉微信退款失败，retun={}", b);
					}

				}
			} else {
				log.error("微信支付异步回掉修改订单状态失败orderno={},price={}分", orderNo, order.getTotelPrice());
				errorOrderService.inseterErrorOrder(orderNo, Cons.ERROR_ORDER_TYPE.PAY_ERROR,
						"微信支付异步回掉修改订单状态失败,orderno=" + orderNo + ",price=" + order.getTotelPrice() + "分");
			}
		}
		/*if (order == null || !order.getStatus().equals(Cons.ORDER_STATUS.PAID)) {
			log.error("微信支付成功异步回掉修改订单状态,但订单不存在或者状态不为待支付，order={}", JSONObject.toJSONString(order));
			return;
		} else {
			order.setStatus(Cons.ORDER_STATUS.USED);
			order.setPayTime(new Date());
			int i = ordersMapper.updateByPrimaryKeySelective(order);
			if (i > 0) {
				log.info("微信支付异步回掉修改订单状态后开始调用票务系统order={}", JSONObject.toJSONString(order));
				// 支付异步回掉后调用分销系统修改订单状态为已支付
				ReturnResult updateOrderToPayment = ticketService.updateOrderToPayment(order);
				if (updateOrderToPayment.getStatus() != 200) {
					// TODO 记录异常日志，支付回掉修改订单状态失败
					log.error("微信支付异步回掉修改订单状态成功，分销系统修改订单状态为已支付失败，直接申请退款");
					errorOrderService.inseterErrorOrder(orderNo, Cons.ERROR_ORDER_TYPE.OUT_TICKET,
							"微信支付异步回掉修改订单状态成功，分销系统修改订单状态为已支付失败，直接申请退款");
					
					 * ReturnResult r = refundCytOrderByOrder(order);
					 * if(r.getStatus()!=200){ log.error(
					 * "支付成功修改订单状态为已支付成功，票务修改订单为已支付失败，准备自动退款失败，order={}",
					 * JSONObject.toJSONString(order)); }
					 
					log.error("开始自动退款，order={}", JSONObject.toJSONString(order));
					DecimalFormat decimalFormat = new DecimalFormat("#");
					String b = WXPayUtil.refund(order.getOrderNo(), decimalFormat.format(order.getTotelPrice()));
					if ("true".equals(b)) {
						order.setStatus(Cons.ORDER_STATUS.REFUNDEDING);
						order.setPayTime(new Date());
						ordersMapper.updateByPrimaryKeySelective(order);
						log.info("pay>>>微信退款申请成功");
					} else if ("订单已全额退款".equals(b)) {
						log.info("pay>>>订单已全额退款");
					} else {
						log.error("pay>>>掉微信退款失败，retun={}", b);
					}

				}
			} else {
				log.error("微信支付异步回掉修改订单状态失败orderno={},price={}分", orderNo, order.getTotelPrice());
				errorOrderService.inseterErrorOrder(orderNo, Cons.ERROR_ORDER_TYPE.PAY_ERROR,
						"微信支付异步回掉修改订单状态失败,orderno=" + orderNo + ",price=" + order.getTotelPrice() + "分");
			}
		}*/
	}

	@Override
	public ReturnResult pay(String orderNo) {
		Orders order = ordersMapper.getOrderByOrderNo(orderNo);
		if (order == null || !order.getStatus().equals(Cons.ORDER_STATUS.PAID)) {
			log.error("微信支付异步回掉修改订单状态,订单不存在orderno={}", orderNo);
			return ReturnResult.build(500, "订单不存在或者订单状态不正确");
		}
		order.setStatus(Cons.ORDER_STATUS.USED);
		order.setPayTime(new Date());
		int i = ordersMapper.updateByPrimaryKeySelective(order);
		if (i > 0) {
			log.info("微信支付异步回掉修改订单状态后开始调用票务系统order={}", JSONObject.toJSONString(order));
			// 支付异步回掉后调用分销系统修改订单状态为已支付
			ReturnResult updateOrderToPayment = ticketService.updateOrderToPayment(order);
			if (updateOrderToPayment.getStatus() == 200) {
				return ReturnResult.ok();
			} else {
				// TODO 记录异常日志，支付回掉修改订单状态失败
				log.error("微信支付异步回掉修改订单状态成功，分销系统修改订单状态为已支付失败，需要通知用户退款，或系统手动退款，order={}",
						JSONObject.toJSONString(order));
				errorOrderService.inseterErrorOrder(orderNo, Cons.ERROR_ORDER_TYPE.OUT_TICKET,
						"微信支付异步回掉修改订单状态成功，分销系统修改订单状态为已支付失败，需要通知用户退款，或系统手动退款");
			}

		}
		log.error("微信支付异步回掉修改订单状态失败order={}", JSONObject.toJSONString(order));
		errorOrderService.inseterErrorOrder(orderNo, Cons.ERROR_ORDER_TYPE.PAY_ERROR,
				"微信支付异步回掉修改订单状态失败,orderno=" + orderNo + ",price=" + order.getTotelPrice() + "分");
		return ReturnResult.build(500, "付款失败");
	}

	@Override
	public ReturnResult updateOrder(Integer orderId, String status) {
		Orders o = ordersMapper.selectByPrimaryKey(orderId);
		if (null == o) {
			return ReturnResult.build(500, "该订单不存在");
		}
		if (status.equals("1") && o.getStatus().equals(Cons.ORDER_STATUS.PAID)) {
			ReturnResult deleteOTAorder = ticketService.deleteOTAorder(o.getDistOrderNo());
			if (deleteOTAorder.getStatus() == 200) {
				log.info("分销系统取消订单成功，orderno={},cytorderno={}", o.getOrderNo(), o.getDistOrderNo());
				/*
				 * ordersMapper.deleteByPrimaryKey(orderId);
				 * orderDetailsMapper.deleteByOrderId(orderId);
				 * playManMapper.deleteByOrderId(orderId);
				 */
				o.setStatus(Cons.ORDER_STATUS.CANCEL);
				ordersMapper.updateByPrimaryKeySelective(o);
				Set<String> keys = redisTemplate.keys("priceRule:" + "*");
				redisTemplate.delete(keys);
				/*
				 * boolean samedate = DateUtils.isSameDay(o.getPlayTime(), new
				 * Date()); if(samedate){ Integer ticketNum =
				 * orderDetailsMapper.getTicketNum(o.getId()); int stock =
				 * scenicMapper.addInventory(ticketNum); if(stock<=0){
				 * log.error("扣库存失败"); } }
				 */

				return ReturnResult.ok("取消成功");
			} else {
				log.error("分销系统取消订单失败，orderno={},cytorderno={},msg={}", o.getOrderNo(), o.getDistOrderNo(),
						deleteOTAorder.getMsg());
				return deleteOTAorder;
			}
			/*
			 * int deleteByPrimaryKey =
			 * ordersMapper.deleteByPrimaryKey(orderId);
			 * if(deleteByPrimaryKey>0){ //通知票务系统取消订单释放库存
			 * log.info("未支付订单用户取消，通知票务系统取消订单释放库存order={}",JSONObject.
			 * toJSONString(o));
			 * ticketService.deleteOTAorder(o.getDistOrderNo()); return
			 * ReturnResult.ok(); }
			 */
		}
		if (status.equals("4") && o.getStatus().equals(Cons.ORDER_STATUS.DONE)
				|| o.getStatus().equals(Cons.ORDER_STATUS.OVERDUE)) {
			// 调用开发票接口
			return ReturnResult.ok("开票成功");
		}

		if (status.equals("5") && o.getStatus().equals(Cons.ORDER_STATUS.BILL)) {
			// 查看发票链接
			return ReturnResult.ok("查看发票链接");
		}
		return ReturnResult.build(500, "修改订单状态失败");
	}

	@Override
	public Object ticketNotice(String param, String method) {
		Request request = checkParam(param);
		if (request == null) {
			log.error("畅游通通知校验失败param={},method={}", param, method);
			return null;
		}
		if ("noticeOrderConsumed".equals(method)) {// 消费通知
			return noticeOrderConsumed(request);
		} else if ("noticeOrderRefundApproveResult".equals(method)) {// ",
			return noticeRefundApproveResul(request);
		} else {
			return null;
		}
	}

	/**
	 * 处理退款申请结果的业务
	 *
	 * @param request
	 * @return
	 */
	private String noticeRefundApproveResul(Request request) {
		// 转换参数
		NoticeOrderRefundApproveResultRequestBody refundResultBody = (NoticeOrderRefundApproveResultRequestBody) request
				.getBody();
		log.info("退票通知返回refundResultBody={}", JSONObject.toJSON(refundResultBody));
		// 畅游通生成的订单ID
		String partnerorderId = refundResultBody.getOrderInfo().getPartnerorderId();
		// 退款流水号，用于标记每一笔退款，由OTA定义
		String refundSeq = refundResultBody.getOrderInfo().getRefundSeq();
		// 原始订单票数
		String orderQuantity = refundResultBody.getOrderInfo().getOrderQuantity();
		// 退款票数
		String refundQuantity = refundResultBody.getOrderInfo().getRefundQuantity();
		// 退款结果【APPROVE：同意退款，REJECT：拒绝退款】
		String refundResult = refundResultBody.getOrderInfo().getRefundResult();
		// 退款金额
		String orderRefundPrice = refundResultBody.getOrderInfo().getOrderRefundPrice();
		// 退款手续费
		String orderRefundCharge = refundResultBody.getOrderInfo().getOrderRefundCharge();
		log.info("畅游通核销成功返回数据cytreturn={}", JSONObject.toJSON(refundResultBody));
		// 改变订单的业务状态
		Orders order = ordersMapper.getCytOrderByOrderNo(partnerorderId);
		if (refundResult.equals("REJECT")) {
			log.error("畅游通拒绝退款,order={}", JSONObject.toJSON(order));
			order.setStatus(Cons.ORDER_STATUS.REFUND_ERROR);
			order.setRefundTime(new Date());
			ordersMapper.update(order);
			return "true";
		}

		if (order.getStatus().equals(Cons.ORDER_STATUS.REFUNDEDING)) {
			boolean b = false;
			if (order.getTotelPrice() != 0) {
				// 调用微信退款接口
				DecimalFormat decimalFormat = new DecimalFormat("#");
				b = WXPayUtil.refund(order.getOrderNo(), decimalFormat.format(order.getTotelPrice()),
						order.getOrderNo());
			} else {
				b = true;
			}
			if (!b) {
				errorOrderService.inseterErrorOrder(order.getOrderNo(), Cons.ERROR_ORDER_TYPE.RETURN_TICKET,
						"畅游通退票成功，系统调用微信退款失败，请手动退票！");
				log.info("畅游通退款成功，微信退款失败返回数据cytreturn={}", JSONObject.toJSON(refundResultBody));
				return "false";
			} else {
				order.setStatus(Cons.ORDER_STATUS.REFUND);
				order.setRefundTime(new Date());
				ordersMapper.update(order);
				return "true";
			}
		}
		return "false";
	}

	private String noticeOrderConsumed(Request request) {
		// 转换参数
		NoticeOrderConsumedRequestBody consumedBody = (NoticeOrderConsumedRequestBody) request.getBody();
		log.info("消费成功通知返回consumedBody={}", JSONObject.toJSON(consumedBody));
		// 畅游通生成的订单ID
		String partnerorderId = consumedBody.getOrderInfo().getPartnerorderId();
		// 电子票消费信息
		String consumeInfo = consumedBody.getOrderInfo().getConsumeInfo();
		// 原始订票总数
		String orderQuantity = consumedBody.getOrderInfo().getOrderQuantity();
		// 累计消费票的总数
		String useQuantity = consumedBody.getOrderInfo().getUseQuantity();
		log.info("畅游通核销成功返回数据cytreturn={}", JSONObject.toJSON(consumedBody));
		// 改变订单的业务状态
		Orders order = ordersMapper.getCytOrderByOrderNo(partnerorderId);
		if (order == null) {
			log.error("核销订单查询不到订单cytorderno={}", partnerorderId);
			return "true";
		}
		// if (order.getStatus().equals(Cons.ORDER_STATUS.TICKET)) {
		order.setStatus(Cons.ORDER_STATUS.DONE);
		int update = ordersMapper.update(order);
		if (update < 0) {
			log.error("畅游通核销成功，系统更新订单状态为已核销失败！order={}", JSONObject.toJSONString(order));
			errorOrderService.inseterErrorOrder(order.getOrderNo(), Cons.ERROR_ORDER_TYPE.OUT_TICKET,
					"畅游通核销成功，系统更新订单状态为已核销失败！");
			return "false";
		} else {
			return "true";
		}
	}

	/**
	 * 检查参数的合法性
	 *
	 * @param param
	 * @return 返回解析后的XML实体数据
	 */
	private Request checkParam(String param) {
		// 检验参数
		AgentStandardExchangeJsonObject paramJson = new AgentStandardExchangeJsonObject();
		try {
			paramJson = JsonUtils.unmarshalFromString(param, AgentStandardExchangeJsonObject.class);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			paramJson.setPlanString(param);
		}
		String data = paramJson.getData();
		if (!StringUtils.equals(Md5Utils.MD5(cytConfiguration.getKey() + data).toUpperCase(),
				paramJson.getSigned().toUpperCase())) {
			log.info("安全密文校验失败");
			return null;
		}
		data = Base64Util.getFromBASE64(data);
		log.info("xml:->{}", data);
		StringReader reader = new StringReader(data);
		try {
			JAXBContext requestJc = JAXBContext.newInstance("com.fjs.scenic.cyt.request");
			Unmarshaller requestUnmarshaller = requestJc.createUnmarshaller();
			Request request = (Request) requestUnmarshaller.unmarshal(reader);
			return request;
		} catch (JAXBException e) {
			log.error(e.toString());
		}
		return null;
	}

	@Override
	public void deleteExpireOrder() {
		List<Orders> ordersList = ordersMapper.select30MinuteOrder();
		if (ordersList != null && ordersList.size() > 0) {
			ordersList.forEach(o -> {
				ReturnResult deleteOTAorder = ticketService.deleteOTAorder(o.getDistOrderNo());
				if (deleteOTAorder.getStatus() == 200) {
					log.info("分销系统取消订单成功，orderno={},cytorderno={}", o.getOrderNo(), o.getDistOrderNo());
					o.setStatus(Cons.ORDER_STATUS.CANCEL);
					ordersMapper.updateByPrimaryKeySelective(o);
					Set<String> keys = redisTemplate.keys("priceRule:" + "*");
					redisTemplate.delete(keys);
				} else {
					log.error("分销系统取消订单失败，orderno={},cytorderno={},msg={}", o.getOrderNo(), o.getDistOrderNo(),
							deleteOTAorder.getMsg());
				}
			});
		}
	}

	@Override
	public List<OrderNum> selectByCount(String field, String param) {
		Map<String, String> map = new HashMap<String, String>();
		map.put("field", field);
		map.put("param", param);
		return ordersMapper.selectByCount(map);
	}

	@Override
	public ReturnResult outTicket(Integer orderId) {
		Orders order = ordersMapper.selectByPrimaryKey(orderId);
		if (order == null || order.getStatus() != Cons.ORDER_STATUS.USED) {
			return ReturnResult.build(500, "订单不存在或者状态不正确");
		}
		ReturnResult updateOrderToPayment = ticketService.updateOrderToPayment(order);
		if (updateOrderToPayment.getStatus() == 200) {
			ErrorOrder eo = new ErrorOrder();
			eo.setOrderId(order.getId());
			errorOrderMapper.delete(eo);
		}
		return updateOrderToPayment;
	}

	@Override
	public List<Map<String, String>> selectPage(OrdersDto orders) {
		return ordersMapper.selectByOption(orders);
	}

	/****************************************/

	/**
	 * @param id
	 *            订单ID
	 * @param status
	 *            订单状态：-1已取消，1未付款，2已付款，3已出票，4已核销，5已开票,6退款中，7已退款，8已过期
	 * @return
	 */
	@Override
	public ReturnResult changeOrderStatus(Integer id, String status) {

		Orders o = ordersMapper.selectByPrimaryKey(id);
		if (null == o) {
			return ReturnResult.build(500, "该订单不存在");
		} else {
			String orderStatus = o.getStatus();
			// 取消
			if (status.equals("-1") && !orderStatus.equals(Cons.ORDER_STATUS.PAID)) {
				return ReturnResult.build(500, "该订单无法取消");
			}
			// 付款
			else if (status.equals(Cons.ORDER_STATUS.USED) && !orderStatus.equals(Cons.ORDER_STATUS.PAID)) {
				return ReturnResult.build(500, "该订单无法付款");
			}
			// 出票
			else if (status.equals(Cons.ORDER_STATUS.TICKET) && !orderStatus.equals(Cons.ORDER_STATUS.USED)) {
				return ReturnResult.build(500, "该订单无法出票");
			}
			// 核销
			else if (status.equals(Cons.ORDER_STATUS.DONE) && !orderStatus.equals(Cons.ORDER_STATUS.TICKET)) {
				return ReturnResult.build(500, "该订单无法核销");
			}
			// 开票
			else if (status.equals(Cons.ORDER_STATUS.BILL) && !orderStatus.equals(Cons.ORDER_STATUS.DONE)) {
				return ReturnResult.build(500, "该订单无法开票");
			}
			// 退款
			else if (status.equals(Cons.ORDER_STATUS.REFUNDEDING)
					&& (!orderStatus.equals(Cons.ORDER_STATUS.USED) && !orderStatus.equals(Cons.ORDER_STATUS.TICKET))) {
				return ReturnResult.build(500, "该订单无法退款");
			}
			// 完成退款(测试直接退款)
			// else if (status.equals(Cons.ORDER_STATUS.REFUND) &&
			// !orderStatus.equals(Cons.ORDER_STATUS.REFUNDEDING) ) {
			// return ReturnResult.build(500, "该订单无法完成退款");
			// }
			// 过期
			else if (status.equals(Cons.ORDER_STATUS.OVERDUE) && !orderStatus.equals(Cons.ORDER_STATUS.TICKET)) {
				return ReturnResult.build(500, "该订单无法完成过期操作");
			}

			if (status.equals(Cons.ORDER_STATUS.PAID)) {// 取消订单直=直接删除并掉分销

				try {
					String deleteOTAorder = otaOrderService.deleteOTAorder(o.getOrderNo().toString());
					JSONObject parseObject = JSONObject.parseObject(deleteOTAorder);

					if (parseObject.get("status").equals("200")) {
						ordersMapper.deleteByPrimaryKey(id);
						return ReturnResult.ok();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				return ReturnResult.build(500, "取消失败！");

			} else if (status.equals(Cons.ORDER_STATUS.REFUNDEDING)) { // 退款
				double money = o.getTotelPrice();
				DecimalFormat decimalFormat = new DecimalFormat("#");
				boolean b = WXPayUtil.refund(o.getOrderNo(), decimalFormat.format(money), o.getOrderNo());
			}

			Orders orders = new Orders();
			orders.setId(id);
			orders.setStatus(status);
			ordersMapper.updateByPrimaryKeySelective(orders);
			return ReturnResult.ok();
		}

	}

	@Override
	public Orders selectByOrderNo(String orderNo) {
		return ordersMapper.selectByOrderNo(orderNo);
	}

	/**
	 * 通过id集合获取订单信息
	 *
	 * @param ids
	 * @return
	 */
	@Override
	public List<Map<String, Object>> selectByIds(List<String> ids) {
		return ordersMapper.selectByIds(ids);
	}

	/**
	 * 管理端 订单查询分页
	 *
	 * @param orders
	 *            查询条件
	 * @param currentPage
	 *            页大小
	 * @param pageSize
	 *            页码
	 * @return
	 */
	@Override
	public Map<String, Object> selectPage1(OrdersDto orders, int currentPage, int pageSize) {
		currentPage = (currentPage == 0) ? 1 : currentPage;
		pageSize = (pageSize == 0) ? 10 : pageSize;
		PageHelper.startPage(currentPage, pageSize);
		List<String> ids = selectIdsPage(orders);
		PageInfo<String> pageInfo = new PageInfo<>(ids);
		List<Map<String, Object>> orderInfos = ids.size() == 0 ? null : selectByIds(ids);
		Map<String, Object> map = new HashMap<>();
		map.put("list", orderInfos);
		map.put("total", pageInfo.getTotal());
		map.put("pageNum", currentPage);
		map.put("pageSize", pageSize);
		return map;
	}

	@Override
	public void updateOrderByExpire() {
		ordersMapper.updateOrderByExpire();
	}

	@Override
	public List<String> selectIdsPage(OrdersDto orders) {
		return ordersMapper.selectIdsPage(orders);
	}

	@Override
	@Async
	public void sendMessage(String ordersNo,String phone) {
		//Map<String, String> phoneByOrdersNo = ordersMapper.getPhoneByOrdersNo(ordersNo);
		//String orderNo = phoneByOrdersNo.get("dist_order_no");
		/*if (StringUtils.isNotBlank(phone) && StringUtils.isNotBlank(orderNo)) {
			Map<String, Object> paramMap = new HashMap<>();
			// 验证码${code}，您正在进行身份验证，打死不要告诉别人哦！
			paramMap.put("oderno", orderNo);
			boolean b = MessageByAli.sendMsg(phone, MessageByAli.captcha, paramMap);
			if(!b){
				log.error("退款短信发送失败，phone={}",phone);
			}else{
				log.error("退款短信发送成功，phone={}",phone);
			}
		}*/
		try {
			Map<String, Object> paramMap = new HashMap<>();
			// 验证码${code}，您正在进行身份验证，打死不要告诉别人哦！
			paramMap.put("oderno", ordersNo);
			boolean b = MessageByAli.sendMsg(phone, MessageByAli.captcha, paramMap);
			if(!b){
				log.error("退款短信发送失败，phone={}",phone);
			}else{
				log.error("退款短信发送成功，phone={}",phone);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	
	
	/**
	 * 
	 * @param nowDate   要比较的时间
	 * @param startDate   开始时间
	 * @param endDate   结束时间
	 * @return   true在时间段内，false不在时间段内
	 * @throws Exception
	 */
	public static boolean hourMinuteBetween(String nowDate, String startDate, String endDate) throws Exception{
		
		SimpleDateFormat format = new SimpleDateFormat("HH:mm");
		
		Date now = format.parse(nowDate);
		Date start = format.parse(startDate);
		Date end = format.parse(endDate);
		
		long nowTime = now.getTime();
		long startTime = start.getTime();
		long endTime = end.getTime();
		
		return nowTime >= startTime && nowTime <= endTime;
	}
	

}
