
package com.tmerclub.cloud.delivery.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.tmerclub.cloud.api.delivery.vo.ShopTransportVO;
import com.tmerclub.cloud.api.product.feign.SpuFeignClient;
import com.tmerclub.cloud.common.cache.constant.DeliveryCacheNames;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.common.database.dto.PageDTO;
import com.tmerclub.cloud.common.database.util.PageUtil;
import com.tmerclub.cloud.common.database.vo.PageVO;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.order.vo.TransfeeFreeVO;
import com.tmerclub.cloud.common.order.vo.TransfeeVO;
import com.tmerclub.cloud.common.order.vo.TransportVO;
import com.tmerclub.cloud.common.response.ResponseEnum;
import com.tmerclub.cloud.common.security.AuthUserContext;
import com.tmerclub.cloud.common.util.BeanUtil;
import com.tmerclub.cloud.common.order.dto.AreaDTO;
import com.tmerclub.cloud.delivery.dto.TransfeeDTO;
import com.tmerclub.cloud.delivery.dto.TransfeeFreeDTO;
import com.tmerclub.cloud.delivery.dto.TransportDTO;
import com.tmerclub.cloud.delivery.mapper.*;
import com.tmerclub.cloud.delivery.model.Transcity;
import com.tmerclub.cloud.delivery.model.TranscityFree;
import com.tmerclub.cloud.delivery.model.Transport;
import com.tmerclub.cloud.delivery.service.TransportService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 运费模板
 *
 * @author tmerclub
 * @date 2020-12-07 15:10:01
 */
@Service
public class TransportServiceImpl implements TransportService {

    @Autowired
    private TransportMapper transportMapper;


    @Autowired
    private TranscityFreeMapper transcityFreeMapper;

    @Autowired
    private TransfeeMapper transfeeMapper;

    @Autowired
    private TranscityMapper transcityMapper;

    @Autowired
    private TransfeeFreeMapper transfeeFreeMapper;

    @DubboReference
    private SpuFeignClient spuFeignClient;


    @Override
    public PageVO<TransportVO> page(PageDTO pageDTO, TransportDTO transportDTO) {
        return PageUtil.doPage(pageDTO, () -> transportMapper.list(transportDTO));
    }


    @Override
    @Cacheable(cacheNames = DeliveryCacheNames.TRANSPORT_BY_ID_PREFIX, key = "#transportId", sync = true)
    public TransportVO getTransportAndAllItemsById(Long transportId) {
        TransportVO transport = transportMapper.getTransportAndTransfeeAndTranscityById(transportId);
        if (transport == null) {
            return null;
        }
        List<TransfeeFreeVO> transFeeFrees = transportMapper.getTransFeeFreeAndTransCityFreeByTransportId(transportId);
        transport.setTransFeeFrees(transFeeFrees);
        return transport;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertTransportAndTransFee(TransportDTO transportDTO) {
        this.checkIsRepeat(transportDTO);
        Transport transport = BeanUtil.map(transportDTO, Transport.class);
        Date createTime = new Date();
        transport.setCreateTime(createTime);
        // 插入运费模板
        transportMapper.save(transport);
        // 插入所有的运费项和城市
        insertTransFeeAndTransCity(transport.getTransportId(), transportDTO.getTransFees());

        // 插入所有的指定包邮条件项和城市
        if (transport.getHasFreeCondition() == 1) {
            insertTransFeeFreeAndTransCityFree(transport.getTransportId(), transportDTO.getTransFeeFrees());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = DeliveryCacheNames.TRANSPORT_BY_ID_PREFIX, key = "#transportDTO.transportId")
    public void updateTransportAndTransFee(TransportDTO transportDTO) {
        TransportVO transportDb = transportMapper.getTransportAndTransfeeAndTranscityById(transportDTO.getTransportId());
        this.checkIsRepeat(transportDTO);
        if (!Objects.equals(transportDb.getShopId(), transportDTO.getShopId())) {
            throw new LuckException(ResponseEnum.UNAUTHORIZED);
        }

        Transport transport = BeanUtil.map(transportDTO, Transport.class);
        // 更新运费模板
        transportMapper.updateById(transport);

        deleteTransportById(transportDTO.getTransportId());

        // 插入所有的运费项和城市
        insertTransFeeAndTransCity(transport.getTransportId(), transportDTO.getTransFees());
        // 插入所有的指定包邮条件项和城市
        if (transport.getHasFreeCondition() == 1) {
            insertTransFeeFreeAndTransCityFree(transport.getTransportId(), transportDTO.getTransFeeFrees());
        }
    }

    private void checkIsRepeat(TransportDTO transportDTO) {
        int count = transportMapper.countByTransName(transportDTO.getShopId(), transportDTO.getTransName(), transportDTO.getSysType(), transportDTO.getTransportId());
        if (count > 0) {
            throw new LuckException("运费模板名称已存在，请重新输入");
        }
        // 查询是否已经存在包邮模板，一个店铺只能有一个包邮模板
        if (transportDTO.getIsFreeFee() == 1) {
            int freeCount = transportMapper.countByFreeAndShopId(transportDTO.getIsFreeFee(), transportDTO.getShopId(), transportDTO.getSysType(), transportDTO.getTransportId());
            if (freeCount > 0) {
                throw new LuckException("已包含包邮模板，不能重复创建");
            }
        }
    }

    private void deleteTransportById(Long transportId) {
        TransportVO dbTransport = getTransportAndAllItemsById(transportId);
        // 删除所有的运费项
        transfeeMapper.deleteByTransportId(dbTransport.getTransportId());
        // 删除所有的指定包邮条件项
        transfeeFreeMapper.deleteTransFeeFreesByTransportId(dbTransport.getTransportId());

        List<Long> transFeeIds = dbTransport.getTransFees().stream().map(TransfeeVO::getTransfeeId).collect(Collectors.toList());
        List<Long> transFeeFreeIds = dbTransport.getTransFeeFrees().stream().map(TransfeeFreeVO::getTransfeeFreeId).collect(Collectors.toList());


        // 删除所有运费项包含的城市
        transcityMapper.deleteBatchByTransFeeIds(transFeeIds);
        if (CollectionUtil.isNotEmpty(transFeeFreeIds)) {
            // 删除所有指定包邮条件项包含的城市
            transcityFreeMapper.deleteBatchByTransFeeFreeIds(transFeeFreeIds);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteTransportAndTransFeeAndTransCityById(Long transportId) {
        int count = spuFeignClient.countByTransportId(transportId).getData();
        if (count > 0) {
            TransportVO dbTransport = getTransportAndAllItemsById(transportId);
            throw new LuckException("模板" + dbTransport.getTransName() + "正在使用中，无法进行删除操作");
        }
        deleteTransportById(transportId);

        // 删除运费模板
        transportMapper.deleteById(transportId);

    }

    private void insertTransFeeAndTransCity(Long transportId, List<TransfeeDTO> transFeeList) {
        for (TransfeeDTO transfeeDTO : transFeeList) {
            transfeeDTO.setTransportId(transportId);
        }
        // 批量插入运费项 并返回运费项id，供下面循环使用
        transfeeMapper.saveBatch(transFeeList);
        List<Transcity> transCities = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (TransfeeDTO transFee : transFeeList) {
            List<AreaDTO> cityList = transFee.getCityList();
            if (CollectionUtil.isEmpty(cityList)) {
                continue;
            }
            // 当地址不为空时
            for (AreaDTO area : cityList) {
                Transcity transcity = new Transcity();
                transcity.setTransfeeId(transFee.getTransfeeId());
                transcity.setCityId(area.getAreaId());
                transCities.add(transcity);
            }
        }

        // 批量插入运费项中的城市
        if (CollectionUtil.isNotEmpty(transCities)) {
            transcityMapper.saveBatch(transCities);
        }
    }

    private void insertTransFeeFreeAndTransCityFree(Long transportId, List<TransfeeFreeDTO> transFeeFrees) {
        if (CollUtil.isEmpty(transFeeFrees)) {
            return;
        }
        for (TransfeeFreeDTO transFeeFree : transFeeFrees) {
            transFeeFree.setTransportId(transportId);
        }
        // 批量插入指定包邮条件项 并返回指定包邮条件项 id，供下面循环使用
        transfeeFreeMapper.saveBatch(transFeeFrees);

        List<TranscityFree> transCityFrees = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (TransfeeFreeDTO transFeeFree : transFeeFrees) {
            List<AreaDTO> cityList = transFeeFree.getFreeCityList();
            if (CollectionUtil.isEmpty(cityList)) {
                // 请选择指定包邮城市
                throw new LuckException("请选择指定包邮城市");
            }
            // 当地址不为空时
            for (AreaDTO area : cityList) {
                TranscityFree transcityFree = new TranscityFree();
                transcityFree.setTransfeeFreeId(transFeeFree.getTransfeeFreeId());
                transcityFree.setFreeCityId(area.getAreaId());
                transCityFrees.add(transcityFree);
            }
        }

        // 批量插入指定包邮条件项中的城市
        if (CollectionUtil.isNotEmpty(transCityFrees)) {
            transcityFreeMapper.saveBatch(transCityFrees);
        }
    }

    @Override
    @CacheEvict(cacheNames = DeliveryCacheNames.TRANSPORT_BY_ID_PREFIX, key = "#transportId")
    public void removeTransportAndAllItemsCache(Long transportId) {

    }

    @Override
    public List<TransportVO> listTransport(Long tenantId) {
        Integer sysType = AuthUserContext.get().getSysType();
        return transportMapper.listTransport(tenantId, sysType);
    }

    @Override
    public List<ShopTransportVO> listTransportByIds(List<Long> ids) {
        return transportMapper.listTransportByIds(ids);
    }

}
