package org.linlinjava.jz.db.service;

import com.github.pagehelper.PageHelper;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.jz.db.dao.JzOrderMapper;
import org.linlinjava.jz.db.dao.OrderMapper;
import org.linlinjava.jz.db.domain.CustomerClient;
import org.linlinjava.jz.db.domain.JzOrder;
import org.linlinjava.jz.db.domain.JzOrderExample;
import org.linlinjava.jz.db.util.OrderUtil;
import org.linlinjava.jz.db.util.RandUtil;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 商城 订单处理
 */
@Service
public class JzOrderService {

    private final JzOrder.Column[] result = new JzOrder.Column[]{JzOrder.Column.id, JzOrder.Column.orderSn, JzOrder.Column.orderStatus, JzOrder.Column.payTime, JzOrder.Column.actualPrice};


    private final Log logger = LogFactory.getLog(JzOrderService.class);

    @Resource
    private OrderMapper orderMapper;

    private final RestTemplate restTemplate = new RestTemplate();

    @Resource
    private JzOrderMapper JzOrderMapper;


    public List<JzOrder> querySelective(String mobile, String orderSn, LocalDateTime start, LocalDateTime end, List<Short> orderStatusArray, Integer orderChannel, Integer page, Integer limit, String sort, String order) {
        JzOrderExample example = new JzOrderExample();
        JzOrderExample.Criteria criteria = example.createCriteria();

        if (!StringUtils.isEmpty(mobile)) {
            criteria.andMobileEqualTo(mobile);
        }

        if (!StringUtils.isEmpty(orderSn)) {
            criteria.andOrderSnEqualTo(orderSn);
        }
        if (start != null) {
            criteria.andCreateTimeGreaterThanOrEqualTo(start);
        }
        if (end != null) {
            criteria.andCreateTimeLessThanOrEqualTo(end);
        }
        if (orderStatusArray != null && orderStatusArray.size() != 0) {
            criteria.andOrderStatusIn(orderStatusArray);
        }

        if (orderChannel != null && orderChannel != 0) {
            criteria.andOrderChannelEqualTo(orderChannel);
        }

        //criteria.andDeletedEqualTo(false);

        if (!StringUtils.isEmpty(sort) && !StringUtils.isEmpty(order)) {
            example.setOrderByClause(sort + " " + order);
        }

        PageHelper.startPage(page, limit);
        return JzOrderMapper.selectByExample(example);
    }

    public int add(JzOrder order) {
        order.setCreateTime(LocalDateTime.now());
        order.setUpdateTime(LocalDateTime.now());
        return JzOrderMapper.insert(order);
    }

    public int count(Integer userId) {
        JzOrderExample example = new JzOrderExample();
        example.or().andUserIdEqualTo(userId).andDeletedEqualTo(false);
        return (int) JzOrderMapper.countByExample(example);
    }

    public JzOrder findById(Integer orderId) {
        return JzOrderMapper.selectByPrimaryKey(orderId);
    }

    public JzOrder findByIdColumn(Integer orderId) {
        return JzOrderMapper.selectByPrimaryKeySelective(orderId, result);
    }

    public JzOrder findById(Integer userId, Integer orderId) {
        JzOrderExample example = new JzOrderExample();
        example.or().andIdEqualTo(orderId).andUserIdEqualTo(userId).andDeletedEqualTo(false);
        return JzOrderMapper.selectOneByExample(example);
    }

    public int countByOrderSn(Integer userId, String orderSn) {
        JzOrderExample example = new JzOrderExample();
        example.or().andUserIdEqualTo(userId).andOrderSnEqualTo(orderSn).andDeletedEqualTo(false);
        return (int) JzOrderMapper.countByExample(example);
    }

    // TODO 这里应该产生一个唯一的订单，但是实际上这里仍然存在两个订单相同的可能性
    public String generateOrderSn(Integer userId) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMdd");
        String now = df.format(LocalDate.now());
        String orderSn = now + RandUtil.getRandomNum(6);
        while (countByOrderSn(userId, orderSn) != 0) {
            orderSn = now + RandUtil.getRandomNum(6);
        }
        return orderSn;
    }

    public List<JzOrder> queryByOrderStatus(Integer userId, List<Short> orderStatus, Integer page, Integer limit, String sort, String order) {
        JzOrderExample example = new JzOrderExample();
        example.setOrderByClause(JzOrder.Column.createTime.desc());
        JzOrderExample.Criteria criteria = example.or();
        criteria.andUserIdEqualTo(userId);
        if (orderStatus != null) {
            criteria.andOrderStatusIn(orderStatus);
        }
        criteria.andDeletedEqualTo(false);
        if (!org.springframework.util.StringUtils.isEmpty(sort) && !org.springframework.util.StringUtils.isEmpty(order)) {
            example.setOrderByClause(sort + " " + order);
        }

        PageHelper.startPage(page, limit);
        return JzOrderMapper.selectByExample(example);
    }

    public List<JzOrder> querySelective(Integer userId, String orderSn, LocalDateTime start, LocalDateTime end, List<Short> orderStatusArray, Integer orderChannel, Integer page, Integer limit, String sort, String order, String mobile) {
        JzOrderExample example = new JzOrderExample();
        JzOrderExample.Criteria criteria = example.createCriteria();

        if (userId > 0) {
            criteria.andUserIdEqualTo(userId);
        }
        if (!org.springframework.util.StringUtils.isEmpty(orderSn)) {
            criteria.andOrderSnEqualTo(orderSn);
        }
        if (!org.springframework.util.StringUtils.isEmpty(mobile)) {
            criteria.andMobileEqualTo(mobile);
        }
        if (start != null) {
            criteria.andCreateTimeGreaterThanOrEqualTo(start);
        }
        if (end != null) {
            criteria.andCreateTimeLessThanOrEqualTo(end);
        }
        if (orderStatusArray != null && orderStatusArray.size() != 0) {
            criteria.andOrderStatusIn(orderStatusArray);
        }

        if (orderChannel != null && orderChannel != 0) {
            criteria.andOrderChannelEqualTo(orderChannel);
        }

        //criteria.andDeletedEqualTo(false);

        if (!org.springframework.util.StringUtils.isEmpty(sort) && !org.springframework.util.StringUtils.isEmpty(order)) {
            example.setOrderByClause(sort + " " + order);
        }

        PageHelper.startPage(page, limit);
        return JzOrderMapper.selectByExample(example);
    }

    public int updateWithOptimisticLocker(JzOrder order) {
        LocalDateTime preUpdateTime = order.getUpdateTime();
        order.setUpdateTime(LocalDateTime.now());
        return orderMapper.updateWithOptimisticLocker(preUpdateTime, order);
    }

    public void deleteById(Integer id) {
        JzOrderMapper.logicalDeleteByPrimaryKey(id);
    }

    public int count() {
        JzOrderExample example = new JzOrderExample();
        example.or().andDeletedEqualTo(false);
        return (int) JzOrderMapper.countByExample(example);
    }

    public List<JzOrder> queryUnpaid(int minutes) {
        JzOrderExample example = new JzOrderExample();
        example.or().andOrderStatusEqualTo(OrderUtil.STATUS_CREATE).andDeletedEqualTo(false);
        return JzOrderMapper.selectByExample(example);
    }

    public List<JzOrder> queryUnconfirm(int days) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime expired = now.minusDays(days);
        JzOrderExample example = new JzOrderExample();
        example.or().andOrderStatusEqualTo(OrderUtil.STATUS_SHIP).andShipTimeLessThan(expired).andDeletedEqualTo(false);
        return JzOrderMapper.selectByExample(example);
    }

    public JzOrder findBySn(String orderSn) {
        JzOrderExample example = new JzOrderExample();
        example.or().andOrderSnEqualTo(orderSn).andDeletedEqualTo(false);
        return JzOrderMapper.selectOneByExample(example);
    }

    public Map<Object, Object> orderInfo(Integer userId) {
        JzOrderExample example = new JzOrderExample();
        example.or().andUserIdEqualTo(userId).andDeletedEqualTo(false);
        List<JzOrder> orders = JzOrderMapper.selectByExampleSelective(example, JzOrder.Column.orderStatus, JzOrder.Column.comments);

        int unpaid = 0;
        int unship = 0;
        int unrecv = 0;
        int uncomment = 0;
        for (JzOrder order : orders) {
            if (OrderUtil.isCreateStatus(order)) {
                unpaid++;
            } else if (OrderUtil.isPayStatus(order)) {
                unship++;
            } else if (OrderUtil.isShipStatus(order)) {
                unrecv++;
            } else if (OrderUtil.isConfirmStatus(order) || OrderUtil.isAutoConfirmStatus(order)) {
                uncomment += order.getComments();
            } else {
                // do nothing
            }
        }

        Map<Object, Object> orderInfo = new HashMap<Object, Object>();
        orderInfo.put("unpaid", unpaid);
        orderInfo.put("unship", unship);
        orderInfo.put("unrecv", unrecv);
        orderInfo.put("uncomment", uncomment);
        return orderInfo;

    }

    public List<JzOrder> queryComment(int days) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime expired = now.minusDays(days);
        JzOrderExample example = new JzOrderExample();
        example.or().andCommentsGreaterThan((short) 0).andConfirmTimeLessThan(expired).andDeletedEqualTo(false);
        return JzOrderMapper.selectByExample(example);
    }

    public void updateAftersaleStatus(Integer orderId, Short statusReject) {
        JzOrder order = new JzOrder();
        order.setId(orderId);
        order.setAftersaleStatus(statusReject);
        order.setUpdateTime(LocalDateTime.now());
        JzOrderMapper.updateByPrimaryKeySelective(order);
    }

    public void updateLogistics(String sn, String trackNo) {
        JzOrder order = findBySn(sn);
        order.setUpdateTime(LocalDateTime.now());
        order.setShipSn(trackNo);
        JzOrderMapper.updateByPrimaryKeySelective(order);
    }


    public void updateOrderCommentTime(Integer orderId) {
        JzOrder order = new JzOrder();
        order.setId(orderId);
        order.setCommentTime(LocalDateTime.now());
        int a = JzOrderMapper.updateByPrimaryKeySelective(order);
        logger.error("更新订单结果:" + a);
    }

    public List<JzOrder> findByUserId(Integer userId) {
        JzOrderExample example = new JzOrderExample();
        example.or().andUserIdEqualTo(userId);
        return JzOrderMapper.selectByExample(example);
    }

    /**
     * 通过手机号同步盒马服务付款单
     *
     * @param phone
     * @return
     */
    public HttpStatus syncHmPaymentOrderByPhone(String phone) {

        String url = "https://servant.lifejingzhi.com/jlifereptileapp/syncHmPaymentOrderByPhone?phone=" + phone;

        //String url = "http://localhost:8084/jlifereptileapp/syncHmPaymentOrderByPhone?phone=" + phone;
        ResponseEntity<String> entity = restTemplate.getForEntity(url, String.class);

        return entity.getStatusCode();
    }

    /**
     * 通过手机号同步盒马服务单
     *
     * @param phone
     * @return
     */
    public HttpStatus syncHmBookOrderByPhone(String phone) {
        String url = "https://servant.lifejingzhi.com/jlifereptileapp/syncHmBookOrderByPhone?phone=" + phone;
        //String url = "http://localhost:8084/jlifereptileapp/syncHmBookOrderByPhone?phone=" + phone;
        ResponseEntity<String> entity = restTemplate.getForEntity(url, String.class);

        return entity.getStatusCode();
    }
}
