package com.ssj.service.weixin.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 java.util.SortedMap;
import java.util.TreeMap;

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.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.ssj.bean.weixin.libmy.domain.TbLibJoin;
import com.ssj.bean.weixin.order.domain.Order;
import com.ssj.bean.weixin.order.domain.OrderRefund;
import com.ssj.bean.weixin.sales.domain.LibOrderDetails;
import com.ssj.bean.weixin.sales.domain.LibVipCode;
import com.ssj.bean.weixin.user.domain.User;
import com.ssj.dao.weixin.order.dao.OrderDao;
import com.ssj.dao.weixin.order.dao.OrderQueryDao;
import com.ssj.framework.core.common.service.BaseServiceImpl;
import com.ssj.framework.core.security.manager.TokenManager;
import com.ssj.framework.core.util.ResponseConstant;
import com.ssj.framework.core.util.ResponseEntity;
import com.ssj.framework.core.util.SystemResourceLocator;
import com.ssj.framework.weixin.pay.OrderHelper;
import com.ssj.framework.weixin.pay.OrderUtil;
import com.ssj.framework.weixin.pay.util.CommonUtil;
import com.ssj.framework.weixin.pay.util.ConfigUtil;
import com.ssj.framework.weixin.pay.util.PayCommonUtil;
import com.ssj.framework.weixin.pay.util.XMLUtil;
import com.ssj.service.weixin.library.service.IBookManagerService;
import com.ssj.service.weixin.library.service.ILibJoinService;
import com.ssj.service.weixin.order.service.OrderRefundService;
import com.ssj.service.weixin.order.service.OrderService;
import com.ssj.service.weixin.sales.service.LibVipCodeService;

@Service(version="1.0")
@Transactional
public class OrderServiceImpl extends BaseServiceImpl<Order, String> implements OrderService{
	
	private Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);

	@Autowired
	private OrderDao  orderDao;
	@Autowired
	private OrderQueryDao  orderQueryDao;
	@Autowired
	private IBookManagerService bookManagerService;
	@Autowired
	private ILibJoinService joinService;
	@Autowired
	private LibVipCodeService  libVipCodeService;
	@Autowired
	private TokenManager tokenManager;
	@Autowired
	private OrderRefundService orderRefundService;//退款	  
	@Override
	public PagingAndSortingRepository<Order, String> getDao() {
		return orderDao;
	}
	@Override
	public void updateOrderStatus(String orderNo, String transactionId,Integer orderStatus) {
		orderDao.updateOrderStatus(orderNo, transactionId, orderStatus);
	}
	@Override
	public void updateOrderClosed(String orderNo) {
		orderDao.updateOrderClosed(orderNo);		
	}
	@Override
	public void updateOrderRefunds(String orderNo) {
		orderDao.updateOrderRefunds(orderNo);	
		
	}
	@Override
	public Page<Map<String, Object>> findForPageList(
			Map<String, Object> searchParams, Pageable pageable) {
		return orderQueryDao.findForPageList(searchParams, pageable);
	}
	@Override
	public Order findUserDepositOrder(String userId) {
		return orderDao.findUserDepositOrder(userId);
	}
	@Override
	public Order findOrderNo(String orderNo) {
		return orderDao.findOrderNo(orderNo);
	}
	@Override
	public List<Map<String, Object>> getOrder(Map<String, Object> searchParams) {
		return orderQueryDao.getOrder(searchParams);
	}
	@Override
	public Page<Map<String, Object>> findForPageLessonServiceList(
			Map<String, Object> searchParams, Pageable pageable) {
		return orderQueryDao.findForPageLessonServiceList(searchParams, pageable);
	}
	@Override
	public Page<Map<String, Object>> findForPageLessonServiceByCourseList(
			Map<String, Object> searchParams, Pageable pageable) {
		return orderQueryDao.findForPageLessonServiceByCourseList(searchParams, pageable);
	}
	@Override
	public Page<Map<String, Object>> findForPageLessonServiceByTeacherList(
			Map<String, Object> searchParams, Pageable pageable) {
		Page<Map<String, Object>>  page=orderQueryDao.findForPageLessonServiceByTeacherList(searchParams, pageable);
		List<String[]> masterList=new ArrayList<String[]>();
		List<String[]> teacherList=new ArrayList<String[]>();
		List<Map<String, Object>> list= page.getContent();
		for (Map<String, Object> map : list) {
			masterList.add(new String[]{map.get("lib_id").toString(),map.get("master_id").toString()});
			teacherList.add(new String[]{map.get("master_id").toString(),map.get("teacher_id").toString()});
		}		
		List<Map<String,Object>> masterMaps=bookManagerService.findMasterIdByLibId(masterList);
		List<Map<String,Object>> teacherMaps=bookManagerService.findTeacherIdByMasterId(teacherList);
		for (Map<String, Object> map : list) {
			String master_id=map.get("master_id").toString();
			String lib_id=map.get("lib_id").toString();
			String teacher_id=map.get("teacher_id").toString();
			for (Map<String, Object> master : masterMaps) {
				String master_id_tmp=master.get("user_id").toString();
				String lib_id_tmp=master.get("lib_id").toString();
				if(master_id_tmp.equals(master_id) && lib_id_tmp.equals(lib_id)){
					map.put("m_name",  master.get("name")!=null ? master.get("name").toString():"");
					map.put("m_telephone", master.get("telephone")!=null ? master.get("telephone").toString() :"");
					break;
				}
				
			}
			for (Map<String, Object> teacher : teacherMaps) {
				String master_id_tmp=teacher.get("master_id").toString();
				String teacher_id_tmp=teacher.get("user_id").toString();
				if(master_id_tmp.equals(master_id) && teacher_id_tmp.equals(teacher_id)){
					map.putAll(teacher);
					break;
				}
			}
		}
		return page;
	}
	@Override
	public Map<String, Object> payInfo(User user, String total_fee,
			String pay_type) {
		
		 String  desc;
         if("4".equals(pay_type)){
      	   desc="私塾家-会员卡支付酬金";
         }else if("7".equals(pay_type)){
      	   desc = "私塾家-图书馆借书首次酬金";
         }else{
      	   desc = "私塾家-图书馆借书普通酬金";
         }
        
			
			SortedMap<Object,Object> params = new TreeMap<Object,Object>();
			Map<String, Object> data = new HashMap<String, Object>();
			String orderNo = OrderUtil.getOrderCode();//生成订单号
			 //下订单，金额为0
			BigDecimal  fee = new BigDecimal(total_fee);
	           if(fee.compareTo(new BigDecimal(0))<=0){
	        	 //微信统一下单接口返回后，生成订单保存到数据库
					Order o = new Order();
					o.setOrderMoney(fee);
					o.setOrderNo(orderNo);
					o.setOrderStatus(1);
					o.setCreateTime(new Date());
					o.setUserId(user.getId());
					o.setPayBy(1);//1 H5支付
					o.setIsClosed(0);
					o.setOrderType(Integer.valueOf(pay_type));
					this.save(o);
					data.put("orderId", o.getId());//向页面传入订单ID
				    data.put("orderNo", orderNo);//向页面传入订单ID
				 	
				 	return data;
	           }
			OrderHelper orderHelper = new OrderHelper();
			try {
				//请求微信统一下单接口，获取最重要的prepay_id.
				Map<String,Object> map = orderHelper.reqestOrder(user.getAccount(),fee.multiply(new BigDecimal(100)).setScale(0,BigDecimal.ROUND_HALF_UP).toString(),orderNo,desc);
				String prepay_id = (String) map.get("prepay_id");
				logger.info("===微信统一下单接口返回的prepay_id："+prepay_id);
				//微信统一下单接口返回后，生成订单保存到数据库
				Order o = new Order();
				o.setOrderMoney(fee);
				o.setOrderNo(orderNo);
				o.setOrderStatus(0);
				o.setPrepayId(prepay_id);
				o.setCreateTime(new Date());
				o.setUserId(user.getId());
				o.setPayBy(1);//1 H5支付
				o.setIsClosed(0);
				o.setOrderType(Integer.valueOf(pay_type));
				o=this.save(o);
				
				
				//页面发起支付接口需要的参数：appId，timeStamp，nonceStr，package，signType，paySign
				String appId = ConfigUtil.APPID;
				String nonceStr = CommonUtil.CreateNoncestr();
				String timeStamp = Long.toString(System.currentTimeMillis());
				String singType = ConfigUtil.SIGN_TYPE;
				String package_ = "prepay_id="+prepay_id;
				
				//组织map去sign签名
				params.put("appId", appId);
	     		params.put("nonceStr", nonceStr);
	     		params.put("package", "prepay_id="+prepay_id);
	     		params.put("signType",singType);
	     		params.put("timeStamp", timeStamp);//最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
	     	
	     		logger.info("===组织支付接口所需的sign签名:"+params);
		        String paySign =  PayCommonUtil.createSign("UTF-8", params,ConfigUtil.PAYKEY);//paySign的生成规则和Sign的生成规则一致
		        
		        //将参数传到页面，组织发起支付
		        data.put("appId", appId);
	     		data.put("timeStamp",timeStamp);
	     		data.put("nonceStr", nonceStr);
	     		data.put("package", package_);
	     		data.put("signType", singType);
		        data.put("paySign", paySign);//paySign的生成规则和Sign的生成规则一致
		        
		        data.put("packageValue", package_);//这里用packageValue是预防package是关键字在js获取值出错   
		        data.put("sendUrl", ConfigUtil.PAY_SUCCESS_URL); //付款成功后跳转的页面
		        data.put("orderId", o.getId());//向页面传入订单ID
		        data.put("orderNo", orderNo);//向页面传入订单ID
		        
		       
		       
			} catch (Exception e) {
				e.printStackTrace();
				
			}
			 return data;
	}
	@Override
	public Map<String, Object> payVIP(User user, LibOrderDetails libOrderDetails) {
         String  desc = "私塾家-支付酬金";
         
       //批量学员购买服务，计算出一共有多少个学员
 		int vipNum=1;
 		if(StringUtils.isNotEmpty(libOrderDetails.getVipId()) 
 				&& libOrderDetails.getVipId().contains(";")){
 			vipNum=	libOrderDetails.getVipId().split(";").length;
 		}
		//单价乘以数量
		BigDecimal  fee = libOrderDetails.getPrice().multiply(new BigDecimal(libOrderDetails.getNumber())).multiply(new BigDecimal(vipNum));
		libOrderDetails.setUserId(user.getId());
		String priceSpecies= libOrderDetails.getPriceSpecies();
		String vipCode= libOrderDetails.getVipCode();
		String libId = libOrderDetails.getLibId();
		TbLibJoin libJoin =joinService.getById(libId);
		libOrderDetails.setLibtype(libJoin.getLibtype());//设置订单的模式
		//以下逻辑适用于广州-深圳
		//作业吧月卡，如果当前时间为当月的最后五天内的，
		//自然月统计收费（设定足月价格后，自动根据当前月剩余时间计算应收金额并完成计费），
		//例：今天是2月27号，则二月要收2天费用加上3月费用，
		//即当月（月费用➗工作日✖️当月剩余工作日天数）➕下月（足月费用）=需要缴费金额
		//服务时长中也需加上当月剩余工作日天数。
//		if("C004".equals(libOrderDetails.getPriceType())){
//			// 获取下个月的最第一天  00:00点
//			Calendar cale = Calendar.getInstance();  
//			cale.add(Calendar.MONTH, 1);  
//			cale.set(Calendar.DAY_OF_MONTH, 1); 
//			int day =DateHelper.daysOfTian(new Date(), cale.getTime());
//			if(day<=5 && day>0){
//				// 获取当前月的第一天  00:00点
//				Calendar startcale = Calendar.getInstance();  
//				startcale.add(Calendar.MONTH, 0);  
//				startcale.set(Calendar.DAY_OF_MONTH, 1);  
//
//				List<WorkDay> monthWorkDays= workDayService.getMonthWorkDay(startcale.getTime());//当月的所有工作日
//				List<WorkDay> workDays= workDayService.getMonthWorkDay(new Date());//当月还有多少个工作日
//				if(workDays!=null && workDays.size()>=1){
//					BigDecimal b1 = new BigDecimal(monthWorkDays.size()); 
//					BigDecimal b2 = new BigDecimal(workDays.size()); 
//					BigDecimal  addFee =libOrderDetails.getPrice().divide(b1,2,BigDecimal.ROUND_HALF_UP).multiply(b2);
//					Calendar endcale = Calendar.getInstance();  
//					endcale.add(Calendar.MONTH, 2);  
//					endcale.set(Calendar.DAY_OF_MONTH, 1);  
//					libOrderDetails.setEndTime(endcale.getTime());
//					BigDecimal extraPrice=addFee.setScale(0, BigDecimal.ROUND_HALF_UP);
//					libOrderDetails.setExtraPrice(extraPrice);
//					fee=fee.add(extraPrice);
//				}
//			}
//		}
		
		if("S001".equals(priceSpecies) || ("S003".equals(priceSpecies)&&"C005".equals(libOrderDetails.getPriceType())) ){
			if(vipCode !=null && vipCode.trim().length()>0){
				LibVipCode  libVipCode  =libVipCodeService.findByVipCodeAndType(vipCode, libId);
				if(libVipCode!=null){
					BigDecimal  discount  =new  BigDecimal(libVipCode.getDiscount());
					//折扣低于80 将进行8折处理
					/*if(discount.compareTo(new BigDecimal("90")) == -1){
						discount = new BigDecimal("90");
					}*/
					fee=fee.multiply(discount).divide(new BigDecimal("100")); 
				}
			}
		}
		logger.info("===私塾家-会员卡支付酬金fee："+fee);
		SortedMap<Object,Object> params = new TreeMap<Object,Object>();
		Map<String, Object> data = new HashMap<String, Object>();
		String orderNo = OrderUtil.getOrderCode();//生成订单号
		
		//fee = new BigDecimal("0.01");
		OrderHelper orderHelper = new OrderHelper();
		String url =(String) SystemResourceLocator.getValue("sys_url")+"/weixin/payment/pay_vip_callback.html";
		try {
			//请求微信统一下单接口，获取最重要的prepay_id.
			Map<String,Object> map = orderHelper.reqestOrder(user.getAccount(),fee.multiply(new BigDecimal(100)).setScale(0,BigDecimal.ROUND_HALF_UP).toString(),orderNo,desc,url);
			String prepay_id = (String) map.get("prepay_id");
			logger.info("===微信统一下单接口返回的prepay_id："+prepay_id);
			//微信统一下单接口返回后，生成订单保存到数据库
			Order o = new Order();
			o.setOrderMoney(fee);
			o.setOrderNo(orderNo);
			o.setOrderStatus(0);
			o.setPrepayId(prepay_id);
			o.setCreateTime(new Date());
			o.setUserId(user.getId());
			o.setPayBy(1);//1 H5支付
			o.setIsClosed(0);
			o.setOrderType(4);
			o=this.save(o);
			libOrderDetails.setCreateTime(new Date());
			libOrderDetails.setOrderId(o.getId());
			libOrderDetails.setOrderNo(orderNo);
			tokenManager.set(orderNo, libOrderDetails,7 * 24 * 3600);//存放redis
			logger.info("==发起支付=orderNo-"+orderNo+"(libOrderDetails)"+JSON.toJSONString(libOrderDetails));
			//页面发起支付接口需要的参数：appId，timeStamp，nonceStr，package，signType，paySign
			String appId = ConfigUtil.APPID;
			String nonceStr = CommonUtil.CreateNoncestr();
			String timeStamp = Long.toString(System.currentTimeMillis());
			String singType = ConfigUtil.SIGN_TYPE;
			String package_ = "prepay_id="+prepay_id;
			
			//组织map去sign签名
			params.put("appId", appId);
			params.put("nonceStr", nonceStr);
			params.put("package", "prepay_id="+prepay_id);
			params.put("signType",singType);
			params.put("timeStamp", timeStamp);//最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
			 data.put("orderNo", orderNo);//向页面传入订单ID
			//logger.info("===组织支付接口所需的sign签名:"+params);
			String paySign =  PayCommonUtil.createSign("UTF-8", params,ConfigUtil.PAYKEY);//paySign的生成规则和Sign的生成规则一致
			
			//将参数传到页面，组织发起支付
			data.put("appId", appId);
			data.put("timeStamp",timeStamp);
			data.put("nonceStr", nonceStr);
			data.put("package", package_);
			data.put("signType", singType);
			data.put("paySign", paySign);//paySign的生成规则和Sign的生成规则一致
			
			data.put("packageValue", package_);//这里用packageValue是预防package是关键字在js获取值出错   
			//data.put("sendUrl", ConfigUtil.PAY_SUCCESS_URL); //付款成功后跳转的页面
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return data;
	}
	@Override
	public ResponseEntity refund(String orderId, BigDecimal refund_fee,String  userId) {
		ResponseEntity responseEntity = new ResponseEntity();
		SortedMap<Object,Object> params = null;
		if(orderId.equals("1")){
			responseEntity.failure(ResponseConstant.CODE_000, "orderId为空");
			return responseEntity;
		}
		try {
			Order order =this.getById(orderId);
			if(order != null){
				if(userId.equals(order.getUserId()) && order.getOrderStatus() == 1){
							String orderNo = order.getOrderNo();
							BigDecimal  total_fee = order.getOrderMoney();
							if(total_fee.compareTo(refund_fee)<0){
								refund_fee = total_fee;
							}
							logger.info("========需要退款的订单号和金额：orderNo:" + orderNo +",refund_fee:"+refund_fee);
							
							OrderHelper helper = new OrderHelper();
							String appid = ConfigUtil.APPID;
							String nonceStr = CommonUtil.CreateNoncestr();
							String mch_id = ConfigUtil.MCH_ID;//"1360047702";
							String refundCode = OrderUtil.getRefundCode();
							
							params = new TreeMap<Object,Object>();
							params.put("appid", appid);
							params.put("mch_id", mch_id);
							params.put("nonce_str", nonceStr);
							params.put("out_trade_no", orderNo);//订单号
							params.put("out_refund_no", refundCode);//商户系统内部的退款单号，商户系统内部唯一，同一退款单号多次请求只退一笔
							params.put("total_fee", total_fee.multiply(new BigDecimal(100)).toString());//订单总金额，单位为分，只能为整数
							params.put("refund_fee", refund_fee.multiply(new BigDecimal(100)).toString());//(此处退款金额=订单总结额)退款总金额，订单总金额，单位为分，只能为整数
							params.put("op_user_id", mch_id);//操作员帐号, 默认为商户号
							String sign =  PayCommonUtil.createSign("UTF-8", params,ConfigUtil.PAYKEY);
							params.put("sign", sign);
							String result = helper.refundPost(params,"https://api.mch.weixin.qq.com/secapi/pay/refund","退款");
					        logger.info("===请求微信退款接口返回结果:"+result);
					        Map<String, Object> map = XMLUtil.doXMLParse(result);
					        if (map.get("return_code").toString().equalsIgnoreCase("SUCCESS") && map.get("result_code").toString().equalsIgnoreCase("SUCCESS")) {
					        	//数据库操作 
					        	OrderRefund re = new OrderRefund();
						        re.setOrderNo(orderNo);
						        re.setRefundNo(refundCode);
						        re.setTransactionId((String)map.get("transaction_id"));
						        re.setTotalFee(total_fee);
						        re.setRefundTotalFee(total_fee);
						        re.setRefundStatus(1);
						        re.setCreateTime(new Date());
						        orderRefundService.save(re);
						        order.setOrderStatus(4);//已退款
						        this.save(order);
					        }
						responseEntity.success("退款成功");
					}
			}
			else{
				responseEntity.failure(ResponseConstant.CODE_000, "订单不存在");
			}
		} catch (Exception e) {
			e.printStackTrace();
			responseEntity.failure(ResponseConstant.CODE_000, "服务器发生异常，请稍后重试");
		}
		return responseEntity;
		
	}
	
}
