package com.buy507.mall.service.impl;

import java.math.BigDecimal;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import com.buy507.mall.common.api.CommonResult;
import com.buy507.mall.common.util.MD5Util;
import com.buy507.mall.component.AutoConfirmReceivingSender;
import com.buy507.mall.component.DistributeSender;
import com.buy507.mall.component.RedisLock;
import com.buy507.mall.dao.OmsOrderDao;
import com.buy507.mall.dao.OmsOrderOperateHistoryDao;
import com.buy507.mall.dto.LogisticsResult;
import com.buy507.mall.dto.OmsMoneyInfoParam;
import com.buy507.mall.dto.OmsOrderDeliveryParam;
import com.buy507.mall.dto.OmsOrderDetail;
import com.buy507.mall.dto.OmsOrderQueryParam;
import com.buy507.mall.dto.OmsOrderResult;
import com.buy507.mall.dto.OmsReceiverInfoParam;
import com.buy507.mall.mapper.DmsMemberTradeRecordMapper;
import com.buy507.mall.mapper.DmsOfflinePaymentRecordMapper;
import com.buy507.mall.mapper.OmsExpressCompanyMapper;
import com.buy507.mall.mapper.OmsOrderItemMapper;
import com.buy507.mall.mapper.OmsOrderMapper;
import com.buy507.mall.mapper.OmsOrderOperateHistoryMapper;
import com.buy507.mall.mapper.PmsProductMapper;
import com.buy507.mall.mapper.PmsSkuStockMapper;
import com.buy507.mall.mapper.UmsMemberMapper;
import com.buy507.mall.model.DmsMemberTradeRecord;
import com.buy507.mall.model.DmsOfflinePaymentRecord;
import com.buy507.mall.model.ItemType;
import com.buy507.mall.model.OmsExpressCompany;
import com.buy507.mall.model.OmsOrder;
import com.buy507.mall.model.OmsOrderExample;
import com.buy507.mall.model.OmsOrderItem;
import com.buy507.mall.model.OmsOrderItemExample;
import com.buy507.mall.model.OmsOrderOperateHistory;
import com.buy507.mall.model.PmsProduct;
import com.buy507.mall.model.PmsSkuStock;
import com.buy507.mall.model.UmsMember;
import com.buy507.mall.service.OmsOrderService;
import com.github.pagehelper.PageHelper;
import com.google.gson.Gson;

/**
 * 订单管理Service实现类
 */
@Service
public class OmsOrderServiceImpl implements OmsOrderService {
	
    @Autowired
    private OmsOrderMapper orderMapper;
    
    @Autowired
    private OmsOrderDao orderDao;
    
    @Autowired
    private OmsOrderItemMapper orderItemMapper;
    
    @Autowired
    private OmsOrderOperateHistoryDao orderOperateHistoryDao;
    
    @Autowired
    private OmsOrderOperateHistoryMapper orderOperateHistoryMapper;
    
    @Autowired
    private DmsOfflinePaymentRecordMapper offlinePaymentRecordMapper;
    
    @Autowired
    private PmsProductMapper productMapper;
    
    @Autowired
    private PmsSkuStockMapper skuStockMapper;
    
    @Autowired
    private OmsExpressCompanyMapper expressCompanyMapper;
    
    @Autowired
    private RestTemplate restTemplate;
    
    @Autowired
    private DistributeSender distributeSender;
    
    @Autowired
    private AutoConfirmReceivingSender autoConfirmReceivingSender;
   
    @Autowired
    private UmsMemberMapper memberMapper;
    
    @Autowired
    private ExecutorService executorService;
    
    @Autowired
    private DmsMemberTradeRecordMapper memberTradeRecordMapper;
    
    @Autowired
    private RedisLock redisLock;
    
    @Value("${kuaidi100.url}")
    private String KUAIDI100_URL;
    
    @Value("${kuaidi100.customer}")
    private String KUAIDI100_CUSTOMER;
    
    @Value("${kuaidi100.key}")
    private String KUAIDI100_KEY;

    @Override
    public List<OmsOrderResult> list(OmsOrderQueryParam queryParam, Integer pageSize, Integer pageNum) {
        PageHelper.startPage(pageNum, pageSize);
        return orderDao.getList(queryParam);
    }

    @Override
    public int delivery(List<OmsOrderDeliveryParam> deliveryParamList) {
        //批量发货
        int count = orderDao.delivery(deliveryParamList);
        //添加操作记录
        List<OmsOrderOperateHistory> operateHistoryList = deliveryParamList.stream()
                .map(omsOrderDeliveryParam -> {
                    OmsOrderOperateHistory history = new OmsOrderOperateHistory();
                    history.setOrderId(omsOrderDeliveryParam.getOrderId());
                    history.setCreateTime(new Date());
                    history.setOperateMan("后台管理员");
                    history.setOrderStatus(2);
                    history.setNote("完成发货");
                    return history;
                }).collect(Collectors.toList());
        orderOperateHistoryDao.insertList(operateHistoryList);
        
        OmsOrder order = null;
        for(OmsOrderDeliveryParam deliveryParam : deliveryParamList) {
        	order = orderMapper.selectByPrimaryKey(deliveryParam.getOrderId());
        	//提货方式：0->自提；1->物流
        	if(order.getDeliveryType() != 0) {
        		//到期未收货-自动确认收货处理
            	long receivingDelayTimes = order.getAutoConfirmDay() * 24 * 60 * 60 * 1000;
            	autoConfirmReceivingSender.sendMessage(order.getId(), receivingDelayTimes);
        	}
        }
        
        return count;
    }

    @Override
    public int close(List<Long> ids, String note) {
    	
    	OmsOrder order = null;
    	Date date = new Date();
    	UmsMember member = null;
    	for(Long orderId : ids) {
    		order = orderMapper.selectByPrimaryKey(orderId);
    		//未付款 未删除状态，才操作数据
            if(order.getStatus() == 0 && order.getDeleteStatus() == 0) {
            	order.setStatus(4);
            	order.setModifyTime(date);
        		orderMapper.updateByPrimaryKey(order);
        		
        		//如果使用余额支付，取消订单需要退还余额
        		BigDecimal zero = new BigDecimal(0);
        		int flag = order.getIntegrationAmount().compareTo(zero);
        		//flag = -1,表示IntegrationAmount小于zero；flag = 0,表示IntegrationAmount等于zero；flag = 1,表示IntegrationAmount大于zero；
        		if(flag == 1) {
        			while(true) {
    					long time = System.currentTimeMillis() + RedisLock.TIMEOUT;
    					if(redisLock.lock(String.valueOf(order.getMemberId()), String.valueOf(time))) {
    						member = memberMapper.selectByPrimaryKey(order.getMemberId());
    						member.setBalance(member.getBalance().add(order.getIntegrationAmount())); //修改余额值
    						member.setFreeze(member.getFreeze().subtract(order.getIntegrationAmount())); //修改冻结值
    						memberMapper.updateByPrimaryKey(member);
    						redisLock.unlock(String.valueOf(order.getMemberId()), String.valueOf(time));
    						break;
    					}
    				}
        		}
        		
        		//写入订单历史操作日志
    			OmsOrderOperateHistory history = new OmsOrderOperateHistory();
                history.setOrderId(orderId);
                history.setCreateTime(date);
                history.setOperateMan("后台管理员");
                
                //订单状态：0->待付款；1->待发货；2->已发货；3->已完成；4->已关闭；5->无效订单
                history.setOrderStatus(4);
                history.setNote("取消订单");
                orderOperateHistoryMapper.insert(history);
        		
        		executorService.execute(new Runnable() {
    				@Override
    				public void run() {
    					OmsOrderItemExample example = new OmsOrderItemExample();
    					example.createCriteria().andOrderIdEqualTo(orderId);
    					List<OmsOrderItem> orderItemList = orderItemMapper.selectByExample(example);
    		    		PmsSkuStock skuStock = null;
    		    		for(OmsOrderItem orderItem : orderItemList) {
    		    			while(true) {
    		    				long time = System.currentTimeMillis() + RedisLock.TIMEOUT;
    		    				if(redisLock.lock(String.valueOf(orderItem.getProductId()), String.valueOf(time))) {
    		    					skuStock = skuStockMapper.selectByPrimaryKey(orderItem.getProductSkuId());
    		    	    			skuStock.setLockStock(skuStock.getLockStock() - orderItem.getProductQuantity());
    		    	    			skuStockMapper.updateByPrimaryKey(skuStock);
    		    	    			redisLock.unlock(String.valueOf(orderItem.getProductId()), String.valueOf(time));
    		    	    			break;
    		    				}
    		    			}
    		    		}
    				}
    			});
        		
            }
    		
    	}

        return 1;
    }

    @Override
    public int delete(List<Long> ids) {
        OmsOrder record = new OmsOrder();
        record.setDeleteStatus(1);
        OmsOrderExample example = new OmsOrderExample();
        example.createCriteria().andDeleteStatusEqualTo(0).andIdIn(ids);
        return orderMapper.updateByExampleSelective(record, example);
    }

    @Override
    public OmsOrderDetail detail(Long id) {
    	OmsOrderDetail orderDetail = orderDao.getDetail(id);
    	DmsOfflinePaymentRecord paymentRecord = offlinePaymentRecordMapper.selectOneByOrderId(id);
    	orderDetail.setPaymentRecord(paymentRecord);
        return orderDetail;
    }

    @Override
    public int updateReceiverInfo(OmsReceiverInfoParam receiverInfoParam) {
        OmsOrder order = new OmsOrder();
        order.setId(receiverInfoParam.getOrderId());
        order.setReceiverName(receiverInfoParam.getReceiverName());
        order.setReceiverPhone(receiverInfoParam.getReceiverPhone());
        order.setReceiverPostCode(receiverInfoParam.getReceiverPostCode());
        order.setReceiverDetailAddress(receiverInfoParam.getReceiverDetailAddress());
        order.setReceiverProvince(receiverInfoParam.getReceiverProvince());
        order.setReceiverCity(receiverInfoParam.getReceiverCity());
        order.setReceiverRegion(receiverInfoParam.getReceiverRegion());
        order.setModifyTime(new Date());
        int count = orderMapper.updateByPrimaryKeySelective(order);
        //插入操作记录
        OmsOrderOperateHistory history = new OmsOrderOperateHistory();
        history.setOrderId(receiverInfoParam.getOrderId());
        history.setCreateTime(new Date());
        history.setOperateMan("后台管理员");
        history.setOrderStatus(receiverInfoParam.getStatus());
        history.setNote("修改收货人信息");
        orderOperateHistoryMapper.insert(history);
        return count;
    }

    @Override
    public int updateMoneyInfo(OmsMoneyInfoParam moneyInfoParam) {
        OmsOrder order = new OmsOrder();
        order.setId(moneyInfoParam.getOrderId());
        order.setFreightAmount(moneyInfoParam.getFreightAmount());
        order.setDiscountAmount(moneyInfoParam.getDiscountAmount());
        order.setModifyTime(new Date());
        int count = orderMapper.updateByPrimaryKeySelective(order);
        //插入操作记录
        OmsOrderOperateHistory history = new OmsOrderOperateHistory();
        history.setOrderId(moneyInfoParam.getOrderId());
        history.setCreateTime(new Date());
        history.setOperateMan("后台管理员");
        history.setOrderStatus(moneyInfoParam.getStatus());
        history.setNote("修改费用信息");
        orderOperateHistoryMapper.insert(history);
        return count;
    }

    @Override
    public int updateNote(Long id, String note, Integer status) {
        OmsOrder order = new OmsOrder();
        order.setId(id);
        order.setNote(note);
        order.setModifyTime(new Date());
        int count = orderMapper.updateByPrimaryKeySelective(order);
        OmsOrderOperateHistory history = new OmsOrderOperateHistory();
        history.setOrderId(id);
        history.setCreateTime(new Date());
        history.setOperateMan("后台管理员");
        history.setOrderStatus(status);
        history.setNote("修改备注信息："+note);
        orderOperateHistoryMapper.insert(history);
        return count;
    }

	@Override
	public CommonResult paymentConfirm(Long id) {
		OmsOrder order = orderMapper.selectByPrimaryKey(id);
		if(order == null) {
			return CommonResult.failed("未查询到订单信息");
		}
		DmsOfflinePaymentRecord paymentRecord = offlinePaymentRecordMapper.selectOneByOrderId(order.getId());
		if(paymentRecord == null) {
			return CommonResult.failed("未查询支付信息");
		}
		if(paymentRecord.getConfirmStatus() == 0) {
			Date date = new Date();
			//确认状态：0->未确认；1->已确认
			paymentRecord.setConfirmStatus(1);
			paymentRecord.setConfirmTime(date);
			//订单状态：0->待付款；1->待发货；2->已发货；3->已完成；4->已关闭；5->无效订单
			
			//提货方式：0->自提；1->物流
			if(order.getDeliveryType() == 0) {
				order.setStatus(2);
			} else {
				order.setStatus(1);
			}
			
			order.setModifyTime(date);
			order.setPaymentTime(date);
			orderMapper.updateByPrimaryKey(order);
			offlinePaymentRecordMapper.updateById(paymentRecord);
			
			BigDecimal zero = new BigDecimal(0);
			int flag = order.getIntegrationAmount().compareTo(zero);
			UmsMember member = memberMapper.selectByPrimaryKey(order.getMemberId());
			
			//flag = -1,表示IntegrationAmount小于zero；flag = 0,表示IntegrationAmount等于zero；flag = 1,表示IntegrationAmount大于zero；
			if(flag == 1) {
				
				//写入会员交易记录表
				DmsMemberTradeRecord tradeRecord = new DmsMemberTradeRecord();
				tradeRecord.setMemberId(member.getId());
				tradeRecord.setItemType(ItemType.IntegralShopping); //积分购物
				tradeRecord.setNote("积分抵扣");
				tradeRecord.setTitle("积分抵扣");
				tradeRecord.setValue(order.getIntegrationAmount());
				tradeRecord.setType(1); //收支类型：0->收入；1->支出
				tradeRecord.setCreateTime(date);
				memberTradeRecordMapper.insert(tradeRecord);
				
				while(true) {
					long time = System.currentTimeMillis() + RedisLock.TIMEOUT;
					if(redisLock.lock(String.valueOf(member.getId()), String.valueOf(time))) {
						member = memberMapper.selectByPrimaryKey(member.getId());
						member.setFreeze(member.getFreeze().subtract(order.getIntegrationAmount())); //修改冻结值
						memberMapper.updateByPrimaryKey(member);
						redisLock.unlock(String.valueOf(member.getId()), String.valueOf(time));
						break;
					}
				}
				
			}
			
			//修改商品库存信息需要加锁，影响前台响应，所以用线程来处理
			executorService.execute(new Runnable() {
				
				@Override
				public void run() {
					//库存变动
					//查询订单商品项
					OmsOrderItemExample example = new OmsOrderItemExample();
					example.createCriteria().andOrderIdEqualTo(order.getId());
					
					List<OmsOrderItem> orderItemList = orderItemMapper.selectByExample(example);
					PmsSkuStock skuStock = null;
					PmsProduct product = null;
					for(OmsOrderItem orderItem : orderItemList) {
						while(true) {
							long time = System.currentTimeMillis() + RedisLock.TIMEOUT;
							if(redisLock.lock(orderItem.getProductId().toString(), String.valueOf(time))) {
								skuStock = skuStockMapper.selectByPrimaryKey(orderItem.getProductSkuId());
								if(skuStock != null) {
									skuStock.setLockStock(skuStock.getLockStock() - orderItem.getProductQuantity());
									skuStock.setStock(skuStock.getStock() - orderItem.getProductQuantity());
									skuStock.setSale((skuStock.getSale() == null ? 0 : skuStock.getSale()) + orderItem.getProductQuantity());
									skuStockMapper.updateByPrimaryKey(skuStock);
								}
								
								product = productMapper.selectByPrimaryKey(orderItem.getProductId());
								if(product != null) {
									product.setStock(product.getStock() - orderItem.getProductQuantity());
									product.setSale((product.getSale() == null ? 0 : product.getSale()) + orderItem.getProductQuantity());
									productMapper.updateByPrimaryKey(product);
								}
								redisLock.unlock(orderItem.getProductId().toString(), String.valueOf(time));
								break;
							}
						}
					}
				}
			});
			
			//分销处理
			distributeSender.sendMessage(order.getId());
			
		}
		
		return CommonResult.success(null);
	}

	@Override
	public CommonResult getLogistics(Long id) {
		LogisticsResult result = new LogisticsResult();
		OmsOrder order = orderMapper.selectByPrimaryKey(id);
		if(order != null && !StringUtils.isEmpty(order.getDeliverySn())) {
			OmsExpressCompany company = expressCompanyMapper.selectOneByName(order.getDeliveryCompany());
			if(company != null) {
				Map<String, String> param = new HashMap<>();
				param.put("com", company.getCode());
				param.put("num", order.getDeliverySn());
				
			    String paramJson = new Gson().toJson(param);
			    
			    String sign = MD5Util.MD5Encode(paramJson + KUAIDI100_KEY + KUAIDI100_CUSTOMER, "utf-8").toUpperCase();
			    HashMap<String, String> params = new HashMap<>();
			    params.put("param", paramJson);
			    params.put("sign", sign);
			    params.put("customer", KUAIDI100_CUSTOMER);
			    String url = KUAIDI100_URL + "?param=" + paramJson + "&sign=" + sign + "&customer=" + KUAIDI100_CUSTOMER;
			    URI uri = UriComponentsBuilder.fromHttpUrl(url).build().encode(Charset.forName("UTF-8")).toUri();
			    ResponseEntity<String> response = restTemplate.getForEntity(uri, String.class);
			    Map<String, Object> object = new Gson().fromJson(response.getBody(), HashMap.class);
			    if("ok".equals(String.valueOf(object.get("message")))) {
			    	//快递单当前状态，包括0在途，1揽收，2疑难，3签收，4退签，5派件，6退回等7个状态
			    	String state = String.valueOf(object.get("state"));
			    	result.setData(object.get("data"));
			    	result.setState(state);
			    	if("0".equals(state)) {
			    		result.setStateName("在途");
			    	} else if("1".equals(state)) {
			    		result.setStateName("揽收");
			    	} else if("2".equals(state)) {
			    		result.setStateName("疑难");
			    	} else if("3".equals(state)) {
			    		result.setStateName("签收");
			    	} else if("4".equals(state)) {
			    		result.setStateName("退签");
			    	} else if("5".equals(state)) {
			    		result.setStateName("派件");
			    	} else {
			    		result.setStateName("退回");
			    	}
			    	return CommonResult.success(result);
			    } else {
			    	return CommonResult.failed(String.valueOf(object.get("message")));
			    }
			}
		}
		return CommonResult.failed();
	}

	@Override
	public CommonResult confirmReceiving(Long id, boolean confirmFlag) {
		
		OmsOrder order = orderMapper.selectByPrimaryKey(id);
    	if(order == null) {
    		return CommonResult.failed("未查询到订单信息");
    	}
    	
    	if(order.getStatus() == 2) {
    		//确认收货状态：0->未确认；1->已确认
        	order.setConfirmStatus(1); //已确认
        	
        	//订单状态：0->待付款；1->待发货；2->已发货；3->已完成；4->已关闭；5->无效订单
        	order.setStatus(3); //已完成
        	Date date = new Date();
        	order.setReceiveTime(date);
        	order.setModifyTime(date);
        	orderMapper.updateByPrimaryKey(order);
        	
    		//写入订单历史操作日志
			OmsOrderOperateHistory history = new OmsOrderOperateHistory();
            history.setOrderId(id);
            history.setCreateTime(date);
            if(confirmFlag) {
            	history.setOperateMan("自动程序");
            } else {
            	history.setOperateMan("后台管理员");
            }
            
            //订单状态：0->待付款；1->待发货；2->已发货；3->已完成；4->已关闭；5->无效订单
            history.setOrderStatus(3);
            history.setNote("完成确认收货");
            orderOperateHistoryMapper.insert(history);
        	
    	}
		
		return CommonResult.success(null, "确认提货成功");
	}
	
	/*
	@Override
	public CommonResult returnGoods(Long id) {
		
		OmsOrder order = orderMapper.selectByPrimaryKey(id);
    	if(order == null) {
    		return CommonResult.failed("未查询到订单信息");
    	}
    	
    	//支付方式：0->未支付；1->支付宝；2->微信；3->线下支付
    	if(order.getPayType() == 0) {
    		return CommonResult.failed("订单未支付，不支持退货");
    	}
    	
    	//分销结算状态（0->未结算；1->已结算；2->不结算）
    	if(order.getSettlementStatus() == 1) {
    		return CommonResult.failed("订单已结算，系统不支持退货，请线下退货");
    	} else if(order.getSettlementStatus() == 2) {
    		return CommonResult.failed("订单已修改为不参与结算，请不要重复操作");
    	} else {
    		order.setSettlementStatus(2);
    		orderMapper.updateByPrimaryKey(order);
    	}
    	
    	List<DmsMemberFreezeAccountRecord> freezeAccountRecords = memberFreezeAccountRecordMapper.selectByOrderId(id);
    	UmsMember member = null;
    	
    	//修改会员分销的冻结金额
    	if(freezeAccountRecords != null && !freezeAccountRecords.isEmpty()) {
    		for(DmsMemberFreezeAccountRecord freezeAccountRecord : freezeAccountRecords) {
    			member = memberMapper.selectByPrimaryKey(freezeAccountRecord.getMemberId());
    			
    			while(true) {
    				long time = System.currentTimeMillis() + RedisLock.TIMEOUT;
    				if(redisLock.lock(String.valueOf(member.getId()), String.valueOf(time))) {
    					member = memberMapper.selectByPrimaryKey(member.getId());
    					member.setFreeze(member.getFreeze().subtract(freezeAccountRecord.getValue())); //修改冻结值
    					memberMapper.updateByPrimaryKey(member);
    					redisLock.unlock(String.valueOf(member.getId()), String.valueOf(time));
    					break;
    				}
    			}
    		}
    	}
    	
    	return CommonResult.success(null, "退货成功");
		
	}
	*/
}
