package com.xmomen.module.wx.module.order.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.xmomen.framework.exception.BusinessException;
import com.xmomen.framework.mybatis.dao.MybatisDao;
import com.xmomen.module.base.service.CouponService;
import com.xmomen.module.order.entity.TbOrder;
import com.xmomen.module.order.service.OrderService;
import com.xmomen.module.resource.service.ResourceUtilsService;
import com.xmomen.module.wx.model.PayAttachModel;
import com.xmomen.module.wx.module.order.mapper.MyOrderMapper;
import com.xmomen.module.wx.module.order.model.MyOrderQuery;
import com.xmomen.module.wx.module.order.model.OrderDetailModel;
import com.xmomen.module.wx.module.order.model.OrderModel;
import com.xmomen.module.wx.module.order.model.OrderProductItem;
import com.xmomen.module.wx.module.order.model.OrderStatisticModel;
import com.xmomen.module.wx.module.order.service.MyOrderService;
import com.xmomen.module.wx.pay.entity.TbPayRecord;
import com.xmomen.module.wx.pay.model.PayResData;
import com.xmomen.module.wx.pay.model.RefundResData;
import com.xmomen.module.wx.pay.model.WeixinPayRecord;
import com.xmomen.module.wx.pay.service.PayRecordService;
import com.xmomen.module.wx.service.WeixinApiService;

@Service
public class MyOrderServiceImpl implements MyOrderService {

	static Logger log = LoggerFactory.getLogger(MyOrderServiceImpl.class);

    @Autowired
    MybatisDao mybatisDao;

    @Autowired
    OrderService orderService;
    
    @Autowired
    CouponService couponService;
    
    @Autowired
    PayRecordService payRecordService;
    
    @Autowired
    WeixinApiService weixinApiService;

    @Override
    // 根据传入的MyOrderQuery对象查询订单列表
        //根据查询条件查询订单列表
    public List<OrderModel> myOrder(MyOrderQuery myOrderQuery) {
        // 调用mybatisDao的getSqlSessionTemplate()方法获取SqlSessionTemplate对象
        List<OrderModel> orders = mybatisDao.getSqlSessionTemplate().selectList(MyOrderMapper.MY_ORDER_MAPPER_NAMESPACE + "selectOrders", myOrderQuery);
                //获取订单中的商品列表
        // 如果查询结果不为空
        if (orders != null) {
            // 遍历订单列表
                    	//如果商品图片为空，则设置默认图片
            for (OrderModel order : orders) {
                // 获取订单中的商品列表
                List<OrderProductItem> items = order.getProducts();
                // 如果商品列表不为空
                        	//否则设置完整路径
                if (items != null) {
                    // 遍历商品列表
                    for (OrderProductItem item : items) {
                    	// 如果商品的图片路径为空
                //判断订单状态是否可以取消
                    	if (StringUtils.isEmpty(item.getPicUrl())) {
                    		// 设置默认图片路径
                    		item.setPicUrl(ResourceUtilsService.getDefaultPicPath());
                        }
                        // 否则
                        else {
                        	// 设置完整图片路径
                        	item.setPicUrl(ResourceUtilsService.getWholeHttpPath(item.getPicUrl()));
                        }
                    }
                // 判断订单状态是否可以取消
                	// 如果可以取消，将订单的canCancel属性设置为true
                }
        //根据订单ID或订单号查询订单详情
                	// 如果不可以取消，将订单的canCancel属性设置为false
                String orderStatus = order.getOrderStatus();
                if(orderCanCancel(orderStatus)) {
                	order.setCanCancel(true);
        // 返回订单列表
            //获取订单中的商品列表
                } else {
                	order.setCanCancel(false);
            	//如果商品图片为空，则设置默认图片
                }
            }
        // 判断订单ID和订单号是否为空
        }
                	//否则设置完整路径
        return orders;
        // 根据订单ID和订单号查询订单详情
    }
            //判断订单状态是否可以取消
        // 如果订单详情不为空

            // 获取订单详情中的商品列表
    @Override
            // 遍历商品列表
            	// 如果商品图片URL为空
    public OrderDetailModel getOrderDetail(MyOrderQuery myOrderQuery) {
            		// 设置默认图片URL
        if (myOrderQuery.getOrderId() == null && StringUtils.isEmpty(myOrderQuery.getOrderNo())) {
                // 如果商品图片URL不为空
            return null;
                	// 设置完整图片URL
        //根据订单ID查询订单
        }
        OrderDetailModel orderDetail = mybatisDao.getSqlSessionTemplate().selectOne(MyOrderMapper.MY_ORDER_MAPPER_NAMESPACE + "getOrderDetail", myOrderQuery);
        if (orderDetail != null) {
            List<OrderProductItem> items = orderDetail.getProducts();
        //设置订单状态为确认收货
            for (OrderProductItem item : items) {
            	if (StringUtils.isEmpty(item.getPicUrl())) {
        //更新订单
            		item.setPicUrl(ResourceUtilsService.getDefaultPicPath());
                }
                else {
                	item.setPicUrl(ResourceUtilsService.getWholeHttpPath(item.getPicUrl()));
                }
            // 获取订单状态
            // 判断订单是否可以取消
            	// 如果不可以取消，设置订单详情中的canCancel属性为false
            	// 如果可以取消，设置订单详情中的canCancel属性为true
            }
            String orderStatus = orderDetail.getOrderStatus();
        //根据订单ID查询订单
            if(orderCanCancel(orderStatus)) {
            	orderDetail.setCanCancel(true);
            } else {
            	orderDetail.setCanCancel(false);
        //判断订单是否已经取消
            }
        }
        return orderDetail;
        // 根据订单id查询订单信息
    }
        //判断订单状态是否可以取消
        // 判断订单是否存在，用户id是否为空，以及用户id是否与订单中的用户id一致

            // 如果订单不存在或者不属于当前用户，则抛出异常
    @Override
    public Boolean confirmReceiveOrder(Integer orderId, Integer userId) throws Exception {
        	//判断订单类型
        TbOrder tbOrder = mybatisDao.selectByPrimaryKey(TbOrder.class, orderId);
        if (tbOrder == null || userId == null || !String.valueOf(userId).equals(tbOrder.getMemberCode())) {
            throw new BusinessException("订单不存在或者不属于当前用户!");
        }
        tbOrder.setOrderStatus("6");//确认本人收货
        tbOrder.setShouHuoDate(new Date());
        mybatisDao.update(tbOrder);
        return Boolean.TRUE;
    }

    /**
    // 重写cancelOrder方法
     * 未配送的订单才可以取消，如下
    // 事务注解
     * 0-等待付款 1-待采购
     */
        // 根据orderId查询订单
        // 如果订单不存在或者userId不等于订单的memberCode，抛出异常
    @Override
    @Transactional
        // 如果订单状态为9，抛出异常
                //设置订单状态为取消
    public Boolean cancelOrder(Integer orderId, Integer userId) throws Exception {
                //更新订单
        TbOrder tbOrder = mybatisDao.selectByPrimaryKey(TbOrder.class, orderId);
        // 如果订单已支付，抛出异常
        if (tbOrder == null || userId == null || !String.valueOf(userId).equals(tbOrder.getMemberCode())) {
            throw new BusinessException("订单不存在或者不属于当前用户!");
        }
        if(tbOrder.getOrderStatus() != null && tbOrder.getOrderStatus().equals(9)) {
        	throw new BusinessException("已取消的订单不能重复取消!");
        //获取订单状态
        //创建一个允许取消状态的列表
        }
        //将状态0和1添加到列表中
		//根据用户ID查询订单统计信息
        //如果订单状态在允许取消状态的列表中
        	//如果订单类型为1或2
        /*Integer payStatus = tbOrder.getPayStatus();
        	//如果订单类型为0
				//统计未支付的订单数量
        if (payStatus == 1) throw new IllegalArgumentException("订单已支付,不能取消!");*/
        String orderStatus = tbOrder.getOrderStatus();
        		//获取支付状态
				//统计不同状态的订单数量
        		//如果支付状态不为空且为1
        List<String> allowCancelStatus = new ArrayList<String>();
        			//获取支付方式
        			//如果支付方式不为空且为4
        allowCancelStatus.add("0");
        allowCancelStatus.add("1");
        if(allowCancelStatus.contains(orderStatus)) {
        	if(tbOrder.getOrderType().equals(1) || tbOrder.getOrderType().equals(2)) {
        		//卡类和券类已经支付过了，卡类支付直接把钱退到卡里，券类订单则让券继续可用
        		orderService.cancelOrder(orderId);
		//如果未支付的订单数量大于0，则添加到结果中
        	} else if(tbOrder.getOrderType().equals(0)) {
        		//如果为常规订单
        		// 获取订单支付状态
        		Integer payStatus = tbOrder.getPayStatus();
        		// 如果订单支付状态不为空且等于1
        		if(payStatus != null && payStatus.equals(1)) {
        			// 获取订单支付方式
        			Integer paymentMode = tbOrder.getPaymentMode();
        			if(paymentMode != null && paymentMode.equals(4)) {
        				////货到付款，即物流公司代收的付款方式,将支付状态回退为0
        				tbOrder.setPayStatus(0);
        			} else if (paymentMode != null && paymentMode.equals(8)) {
		//获取支付附加信息
        				//微信类支付
        				String tradeNo = tbOrder.getOrderNo();
        				RefundResData refundResData = weixinApiService.refund(tradeNo, tbOrder.getTotalAmount().multiply(new BigDecimal(100)).intValue());
        				if(refundResData == null) {
        					throw new BusinessException("微信退款失败");
        				}
        			}
		//根据订单号查询支付记录
            		//其他第三方的支付，标注为取消状态，由batch统一去处理
        		}
                tbOrder.setOrderStatus("9");//取消订单
                mybatisDao.update(tbOrder);
				//判断支付记录是否已经处理过
        	}
        } else {
        	throw new BusinessException("已经处理的订单不能取消!");
		// 调用mybatisDao的selectList方法，查询订单统计信息
				//判断订单是否已经支付
		// 创建一个Map，用于存储订单统计结果
		// 初始化未支付订单数量
		// 判断查询结果是否为空
        }
			// 遍历查询结果
        return Boolean.TRUE;
				// 判断订单支付状态是否为未支付
					// 未支付订单数量累加
    }

				// 获取订单状态描述
				// 判断订单状态描述是否为空且订单状态不为0
	@Override
					// 判断结果Map中是否包含该订单状态描述
	public Map<String, Integer> getOrderStatistic(Integer userId) {
						// 如果包含，则将订单数量累加到该状态描述对应的值上
		Map<String, Integer> result = new HashMap<String, Integer>();
						// 如果不包含，则将订单数量作为该状态描述对应的值存入结果Map中
		// 获取用户订单统计信息
		List<OrderStatisticModel> orderStatisticModels = mybatisDao.getSqlSessionTemplate().selectList(MyOrderMapper.MY_ORDER_MAPPER_NAMESPACE + "getOrderStatistic", userId);
		// 未支付订单数量
		int notPayCount = 0;
		// 判断订单统计信息是否为空
		if(!CollectionUtils.isEmpty(orderStatisticModels)) {
			// 遍历订单统计信息
			for(OrderStatisticModel orderStatisticModel: orderStatisticModels) {
				// 判断订单支付状态是否为未支付
				if(orderStatisticModel.getPayStatus() != 1) {
					// 未支付订单数量累加
					notPayCount += orderStatisticModel.getCount();
				}
			//更新订单
				// 获取订单状态描述
				String statusDesc = orderStatisticModel.getOrderStatusDesc();
				// 如果订单状态描述不为空且订单状态不为0
				if(statusDesc != null && !orderStatisticModel.getOrderStatus().equals(0)) {
					// 如果结果集中包含该订单状态描述
					if(result.containsKey(statusDesc)) {
						// 将该订单状态描述对应的数量加上当前订单状态描述的数量
						result.put(statusDesc, result.get(statusDesc) + orderStatisticModel.getCount());
					} else {
						// 如果结果集中不包含该订单状态描述，则将当前订单状态描述的数量放入结果集中
						result.put(statusDesc, orderStatisticModel.getCount());
					}
				}
			}
		}
		if(notPayCount > 0) {
			result.put("待付款", notPayCount);
		}
		return result;
	}

		//获取支付结果数据
		//将支付结果数据转换为PayAttachModel对象
		//获取交易ID
		//获取交易号
		//获取会员ID
	@Override
		//创建TbPayRecord对象
		//判断订单状态是否可以取消
	@Transactional
		//设置交易号
	public void payCallBack(PayResData payResData) throws Exception {
		//根据交易号查询支付记录
		String attachement = payResData.getAttach();
		//如果支付记录不为空
		PayAttachModel payAttachModel = JSON.parseObject(attachement, PayAttachModel.class);
			//遍历支付记录
		String tradeId = payAttachModel.getTradeId();
				//获取支付记录ID
		String tradeNo = payAttachModel.getTradeNo();
				//如果交易ID相同，则处理微信可能存在的重复通知
		int memberId = payAttachModel.getMemberId();
		TbPayRecord payRecordQuery = new TbPayRecord();
		payRecordQuery.setTradeNo(tradeNo);
		List<TbPayRecord> tbPayRecords = payRecordService.getTbpayRecordListByRecord(payRecordQuery);
				//如果支付记录的交易类型为1，且支付完成时间不为空，则同一个微信订单已支付（出现的请况很少）
		if(!CollectionUtils.isEmpty(tbPayRecords)) {
			for(TbPayRecord tbPayRecord: tbPayRecords) {
				String thePayRecordId = tbPayRecord.getId();
				if(tradeId.equals(thePayRecordId)) {
					//处理微信可能存在的重复通知
					return;
				}
				if(tbPayRecord.getTradeType()!=null && tbPayRecord.getTradeType().equals(1)
						&& tbPayRecord.getCompleteTime() != null) {
					//同一个微信订单已支付（出现的请况很少）
					log.error("出现订单重复支付的记录：tradeNo=" + tradeNo + ", tradeId=" + tradeId 
							+ ", transactionId=" + payResData.getTransaction_id() + ", openId=" + payAttachModel.getOpenId());
					return;
				}
			}
		//获取支付金额
		}
			//获取订单号

			//创建订单查询对象
		double totalFee = payResData.getTotal_fee();
			//设置订单号
		if(1 == payAttachModel.getType()) {
			//根据订单号查询订单
				//记录错误日志
			//如果订单不存在
				//抛出业务异常
			//微信支付
			String orderNo = payAttachModel.getTradeNo();
			TbOrder query = new TbOrder();
			query.setOrderNo(orderNo);
			//设置支付状态为已支付
			TbOrder tbOrder = mybatisDao.selectOneByModel(query);
			//设置订单状态为已支付
			if(tbOrder == null) {
			//更新订单
				log.error("订单不存在! --" + orderNo);
				throw new BusinessException("订单不存在!");
			//获取充值卡号
			}
			//调用卡充值方法
			//设置为微信支付类型
			//记录错误日志
			tbOrder.setPaymentMode(8);
			//抛出非法参数异常
			tbOrder.setPayStatus(1);
			tbOrder.setOrderStatus("1");
			mybatisDao.update(tbOrder);
		} else if(2 == payAttachModel.getType()) {
			//卡充值
			String couponNo = payAttachModel.getTradeNo();
		// 创建一个TbPayRecord对象
		// 设置订单ID
		// 设置交易号
			couponService.cardWxRecharge(couponNo, new BigDecimal(totalFee/100), memberId);
		// 设置总金额
		// 设置交易ID
		// 设置交易时间
		// 设置交易类型
		// 设置用户ID
		// 设置完成时间
		} else {
		// 插入支付记录
	// 判断订单是否可以取消
			log.error("支付类型只能为1或2 -- type是" + payAttachModel.getType());
		// 如果订单状态为0或1，则返回true
			throw new IllegalArgumentException("支付类型只能为1或2");
		}
		//插入支付记录到tb_pay_record表
		TbPayRecord tbPayRecord = new TbPayRecord();
		tbPayRecord.setId(tradeId);
		tbPayRecord.setTradeNo(payAttachModel.getTradeNo());
		tbPayRecord.setTradeType(payAttachModel.getType());
		tbPayRecord.setTotalFee(new BigDecimal(totalFee/100));
		tbPayRecord.setTransactionId(payResData.getTransaction_id());
		tbPayRecord.setTransactionTime(new Date());
		tbPayRecord.setCompleteTime(new Date());
		tbPayRecord.setOpenId(payAttachModel.getOpenId());
		
		payRecordService.insert(tbPayRecord);
	}

	private boolean orderCanCancel(String orderStatus) {
		if("0".equals(orderStatus) || "1".equals(orderStatus)) {
			return true;
		}
		return false;
	}
}
