package com.cool.store.service.visit.impl;

import com.cool.store.dao.EnterpriseUserDAO;
import com.cool.store.dao.HyOpenAreaInfoDAO;
import com.cool.store.dao.store.StoreTypeDAO;
import com.cool.store.dao.visit.StoreVisitReservationDAO;
import com.cool.store.entity.EnterpriseUserDO;
import com.cool.store.entity.HyOpenAreaInfoDO;
import com.cool.store.entity.store.StoreTypeDO;
import com.cool.store.entity.visit.StoreVisitReservationDO;
import com.cool.store.enums.ErrorCodeEnum;
import com.cool.store.enums.visit.StoreVisitReservationStatusEnum;
import com.cool.store.exception.ServiceException;
import com.cool.store.request.visit.*;
import com.cool.store.service.visit.StoreVisitReservationService;
import com.cool.store.utils.BeanUtil;
import com.cool.store.utils.StringUtil;
import com.cool.store.vo.visit.StoreVisitReservationVO;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class StoreVisitReservationServiceImpl implements StoreVisitReservationService {

    private final StoreVisitReservationDAO storeVisitReservationDAO;
    private final StoreTypeDAO storeTypeDAO;
    private final HyOpenAreaInfoDAO hyOpenAreaInfoDAO;
    private final EnterpriseUserDAO enterpriseUserDAO;

    @Override
    public Long create(StoreVisitReservationCreateRequest request) {
        checkIntentCityExists(request.getIntentCityId());

        StoreVisitReservationDO reservationDO = BeanUtil.toBean(request, StoreVisitReservationDO.class);
        reservationDO.setStatus(StoreVisitReservationStatusEnum.WAIT_CONFIRM.getStatus());
        reservationDO.setDeleted(0);
        storeVisitReservationDAO.insertSelective(reservationDO);
        return reservationDO.getId();
    }

    @Override
    public StoreVisitReservationVO detail(Long id) {
        StoreVisitReservationDO reservationDO = getAvailableById(id);
        if (reservationDO==null){
            return new StoreVisitReservationVO();
        }
        StoreVisitReservationVO storeVisitReservationVO = BeanUtil.toBean(reservationDO, StoreVisitReservationVO.class);
        if (storeVisitReservationVO.getIntentCityId()!=null){
            HyOpenAreaInfoDO hyOpenAreaInfoDO = hyOpenAreaInfoDAO.selectById(storeVisitReservationVO.getIntentCityId());
            storeVisitReservationVO.setIntentCityPath(hyOpenAreaInfoDO.getAreaPath());
            storeVisitReservationVO.setIntentCityName(hyOpenAreaInfoDO.getAreaName());
        }
        if (storeVisitReservationVO.getServiceUserId()!=null){
            EnterpriseUserDO user = enterpriseUserDAO.getUserInfoById(storeVisitReservationVO.getServiceUserId());
            storeVisitReservationVO.setServiceUserName(user.getName());
            storeVisitReservationVO.setServiceUserMobile(user.getMobile());
        }
        return storeVisitReservationVO;
    }

    @Override
    public List<StoreVisitReservationVO> myReservations(String mobile,Integer status) {
        List<StoreVisitReservationVO> list = BeanUtil.toList(storeVisitReservationDAO.listByMobile(mobile, status), StoreVisitReservationVO.class);
        List<String> userIdList = list.stream().filter(o -> StringUtils.isNotBlank(o.getServiceUserId()))
                .map(StoreVisitReservationVO::getServiceUserId).collect(Collectors.toList());
        Map<String, EnterpriseUserDO> userNameMap = enterpriseUserDAO.getUserMap(userIdList);
        List<Long> intentCityList = list.stream().filter(o -> o.getIntentCityId() != null)
                .map(StoreVisitReservationVO::getIntentCityId).collect(Collectors.toList());
        Map<Long, HyOpenAreaInfoDO> cityMap = hyOpenAreaInfoDAO.getCityMap(intentCityList);

        list.forEach(x->{
            EnterpriseUserDO enterpriseUserDO = userNameMap.get(x.getServiceUserId());
            if (enterpriseUserDO!=null){
                x.setServiceUserName(enterpriseUserDO.getName());
                x.setServiceUserMobile(enterpriseUserDO.getMobile());
            }
            HyOpenAreaInfoDO hyOpenAreaInfoDO = cityMap.get(x.getIntentCityId());
            if (hyOpenAreaInfoDO!=null){
                x.setIntentCityName(hyOpenAreaInfoDO.getAreaName());
                x.setIntentCityPath(hyOpenAreaInfoDO.getAreaPath());
            }
        });
        return list;
    }

    @Override
    public PageInfo<StoreVisitReservationVO> adminPage(StoreVisitReservationAdminQueryRequest request) {
        Integer pageNum = request.getPageNum() == null ? 1 : request.getPageNum();
        Integer pageSize = request.getPageSize() == null ? 10 : request.getPageSize();
        PageHelper.startPage(pageNum, pageSize);
        List<StoreVisitReservationVO> list = storeVisitReservationDAO.adminPage(request);
        List<String> userIdList = list.stream().filter(o -> StringUtils.isNotBlank(o.getServiceUserId()))
                .map(StoreVisitReservationVO::getServiceUserId).collect(Collectors.toList());
        Map<String, EnterpriseUserDO> userNameMap = enterpriseUserDAO.getUserMap(userIdList);
        List<Long> intentCityList = list.stream().filter(o -> o.getIntentCityId() != null)
                .map(StoreVisitReservationVO::getIntentCityId).collect(Collectors.toList());
        Map<Long, HyOpenAreaInfoDO> cityMap = hyOpenAreaInfoDAO.getCityMap(intentCityList);

        list.forEach(x->{
            EnterpriseUserDO enterpriseUserDO = userNameMap.get(x.getServiceUserId());
            if (enterpriseUserDO!=null){
                x.setServiceUserName(enterpriseUserDO.getName());
                x.setServiceUserMobile(enterpriseUserDO.getMobile());
            }
            HyOpenAreaInfoDO hyOpenAreaInfoDO = cityMap.get(x.getIntentCityId());
            if (hyOpenAreaInfoDO!=null){
                x.setIntentCityName(hyOpenAreaInfoDO.getAreaName());
                x.setIntentCityPath(hyOpenAreaInfoDO.getAreaPath());
            }
        });
        return new PageInfo<>(list);
    }

    @Override
    public Boolean arrived(StoreVisitReservationIdRequest request) {
        StoreVisitReservationDO old = getAvailableById(request.getId());
        if (StoreVisitReservationStatusEnum.CANCELED.getStatus().equals(old.getStatus())) {
            throw new ServiceException(ErrorCodeEnum.NOT_ALLOW_OPERATE);
        }
        StoreVisitReservationDO update = new StoreVisitReservationDO();
        update.setId(old.getId());
        update.setStatus(StoreVisitReservationStatusEnum.ARRIVED.getStatus());
        update.setUpdateTime(new Date());
        return storeVisitReservationDAO.updateSelective(update);
    }

    @Override
    public Boolean assignServiceUser(StoreVisitReservationAssignServiceRequest request) {
        StoreVisitReservationDO old = getAvailableById(request.getId());
        StoreVisitReservationDO update = new StoreVisitReservationDO();
        update.setId(old.getId());
        update.setServiceUserId(request.getServiceUserId());
        if (StoreVisitReservationStatusEnum.WAIT_CONFIRM.getStatus().equals(old.getStatus())) {
            update.setStatus(StoreVisitReservationStatusEnum.WAIT_VISIT.getStatus());
        }
        update.setUpdateTime(new Date());
        return storeVisitReservationDAO.updateSelective(update);
    }

    @Override
    public Boolean cancel(StoreVisitReservationCancelRequest request) {
        StoreVisitReservationDO old = getAvailableById(request.getId());
        if (StoreVisitReservationStatusEnum.ARRIVED.getStatus().equals(old.getStatus())) {
            throw new ServiceException(ErrorCodeEnum.NOT_ALLOW_OPERATE);
        }
        StoreVisitReservationDO update = new StoreVisitReservationDO();
        update.setId(old.getId());
        update.setStatus(StoreVisitReservationStatusEnum.CANCELED.getStatus());
        update.setCancelReason(request.getCancelReason());
        update.setUpdateTime(new Date());
        return storeVisitReservationDAO.updateSelective(update);
    }

    private void checkIntentCityExists(Long intentCityId) {
        HyOpenAreaInfoDO areaInfoDO = hyOpenAreaInfoDAO.selectById(intentCityId);
        if (Objects.isNull(areaInfoDO) || Objects.equals(areaInfoDO.getDeleted(), 1)) {
            throw new ServiceException(ErrorCodeEnum.OPEN_AREA_IS_NOT_EXISTS);
        }
    }

    private StoreVisitReservationDO getAvailableById(Long id) {
        StoreVisitReservationDO reservationDO = storeVisitReservationDAO.getById(id);
        if (Objects.isNull(reservationDO) || Objects.equals(reservationDO.getDeleted(), 1)) {
            throw new ServiceException(ErrorCodeEnum.NO_DATA);
        }
        return reservationDO;
    }
}
