package com.yc.ship.module.marketing.service.policy;

import com.yc.ship.framework.common.util.collection.CollectionUtils;
import com.yc.ship.module.marketing.dal.dataobject.policydetail.PolicyDetailDO;
import com.yc.ship.module.marketing.dal.mysql.policydetail.PolicyDetailMapper;
import com.yc.ship.module.product.dal.dataobject.voyage.VoyageDO;
import com.yc.ship.module.product.service.voyage.VoyageService;
import com.yc.ship.module.system.api.area.AreaApi;
import com.yc.ship.module.system.api.area.dto.AreaCountryDTO;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import com.yc.ship.module.marketing.controller.admin.policy.vo.*;
import com.yc.ship.module.marketing.dal.dataobject.policy.PolicyDO;
import com.yc.ship.framework.common.pojo.PageResult;
import com.yc.ship.framework.common.util.object.BeanUtils;

import com.yc.ship.module.marketing.dal.mysql.policy.PolicyMapper;

import static com.yc.ship.framework.common.exception.util.ServiceExceptionUtil.exception0;

/**
 * 营销政策 Service 实现类
 *
 * @author 管理员
 */
@Service
@Validated
public class PolicyServiceImpl implements PolicyService {

    @Resource
    private PolicyMapper policyMapper;

    @Resource
    private PolicyDetailMapper policyDetailMapper;

    @Resource
    private AreaApi areaApi;

    @Resource
    private VoyageService voyageService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createPolicy(PolicySaveReqVO createReqVO) {
        // 插入
        PolicyDO policy = BeanUtils.toBean(createReqVO, PolicyDO.class);
        policyMapper.insert(policy);
        handlePolicyDetail(policy.getId(), createReqVO);
        // 返回
        return policy.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePolicy(PolicySaveReqVO updateReqVO) {
        // 更新
        PolicyDO updateObj = BeanUtils.toBean(updateReqVO, PolicyDO.class);
        policyMapper.updateById(updateObj);
    }

    @Override
    public void deletePolicy(Long id) {
        throw exception0(500, "暂不支持删除，请关闭使用状态");
        // 删除
    }

    private void handlePolicyDetail(Long policyId, PolicySaveReqVO reqVO) {
        policyDetailMapper.deleteByPolicyId(policyId);
        List<Long> voyageIds = reqVO.getVoyageIds();
        List<Long> roomModelIds = reqVO.getRoomModelIds();
        List<Long> areaIds = reqVO.getAreaIds();
        BigDecimal discountNum = reqVO.getDiscountNum();
        List<PolicyDetailDO> policyDetailDOList = new ArrayList<>();
        voyageIds.forEach(voyageId -> {
            PolicyDetailDO policyDetailDO = new PolicyDetailDO();
            policyDetailDO.setShipId(reqVO.getShipId());
            policyDetailDO.setPolicyId(policyId);
            policyDetailDO.setVoyageId(voyageId);
            policyDetailDO.setRoomModelIds(roomModelIds);
            policyDetailDO.setAreaIds(areaIds);
            policyDetailDO.setSurplusNum(discountNum);
            policyDetailDOList.add(policyDetailDO);
        });
        if(!policyDetailDOList.isEmpty()) {
            policyDetailMapper.insertBatch(policyDetailDOList);
        }
    }


    @Override
    public PolicyDO getPolicy(Long id) {
        return policyMapper.selectById(id);
    }

    @Override
    public PageResult<PolicyDO> getPolicyPage(PolicyPageReqVO pageReqVO) {
        return policyMapper.selectPage(pageReqVO);
    }

    @Override
    public List<PolicyRespVO> getUsablePolicy(PolicyUsableReqVO reqVO) {
        //获取区域列表
        List<Long> countryIds = reqVO.getCountryIds();
        List<AreaCountryDTO> areaCountryDTOS = areaApi.getAreaCountryListByCountryIds(countryIds);
        Set<Long> areaIds = CollectionUtils.convertSet(areaCountryDTOS, AreaCountryDTO::getAreaId);
        List<Long> roomModelIds = reqVO.getRoomModelIds();
        VoyageDO voyage = voyageService.getVoyage(reqVO.getVoyageId());
        List<PolicyDetailDO> policyDetails = policyDetailMapper.selectListByVoyageId(reqVO.getVoyageId());
        List<PolicyDetailDO> filterPolicyDetails = policyDetails.stream().filter(policyDetailDO -> {
            List<Long> areaIds1 = policyDetailDO.getAreaIds();
            List<Long> roomModelIds1 = policyDetailDO.getRoomModelIds();
            if(CollectionUtils.isAnyEmpty(areaIds1) || CollectionUtils.isAnyEmpty(roomModelIds1)) {
                return false;
            }else {
                return areaIds1.stream().anyMatch(areaIds::contains) && roomModelIds1.stream().anyMatch(roomModelIds::contains);
            }
        }).collect(Collectors.toList());

        List<Long> policyIds = CollectionUtils.convertList(filterPolicyDetails, PolicyDetailDO::getPolicyId);
        if(CollectionUtils.isAnyEmpty(policyIds)) {
            return Collections.emptyList();
        }
        List<PolicyDO> policyList = policyMapper.selectList(policyIds);
        List<PolicyDO> result = policyList.stream().filter(policyDO -> {
            LocalDateTime boardingTime = voyage.getBoardingTime();
            return boardingTime.plusDays(policyDO.getEarlyDays() * -1L).isAfter(LocalDateTime.now());
        }).collect(Collectors.toList());
        List<PolicyRespVO> policyRespVOS = BeanUtils.toBean(result, PolicyRespVO.class);
        Map<Long, PolicyDetailDO> policyDetailDOMap = CollectionUtils.convertMap(filterPolicyDetails, PolicyDetailDO::getPolicyId);
        policyRespVOS.forEach(policyRespVO -> {
            PolicyDetailDO policyDetailDO = policyDetailDOMap.get(policyRespVO.getId());
            if(policyDetailDO != null) {
                policyRespVO.setAreaIds(policyDetailDO.getAreaIds());
                policyRespVO.setRoomModelIds(policyDetailDO.getRoomModelIds());
                policyRespVO.setSurplusNum(policyDetailDO.getSurplusNum());
            }
        });
        return policyRespVOS;
    }

    @Override
    public List<PolicyRespVO> getUsablePolicyByVoyageId(Long voyageId) {
        VoyageDO voyage = voyageService.getVoyage(voyageId);
        List<PolicyDetailDO> policyDetails = policyDetailMapper.selectListByVoyageId(voyageId);
        List<Long> policyIds = CollectionUtils.convertList(policyDetails, PolicyDetailDO::getPolicyId);
        if(CollectionUtils.isAnyEmpty(policyIds)) {
            return Collections.emptyList();
        }
        List<PolicyDO> policyList = policyMapper.selectList(policyIds);
        List<PolicyDO> result = policyList.stream().filter(policyDO -> {
            LocalDateTime boardingTime = voyage.getBoardingTime();
            return boardingTime.plusDays(policyDO.getEarlyDays() * -1L).isAfter(LocalDateTime.now());
        }).collect(Collectors.toList());
        List<PolicyRespVO> policyRespVOS = BeanUtils.toBean(result, PolicyRespVO.class);
        Map<Long, PolicyDetailDO> policyDetailDOMap = CollectionUtils.convertMap(policyDetails, PolicyDetailDO::getPolicyId);
        policyRespVOS.forEach(policyRespVO -> {
            PolicyDetailDO policyDetailDO = policyDetailDOMap.get(policyRespVO.getId());
            if(policyDetailDO != null) {
                policyRespVO.setAreaIds(policyDetailDO.getAreaIds());
                List<AreaCountryDTO> areaCountryListByAreaIds = areaApi.getAreaCountryListByAreaIds(policyDetailDO.getAreaIds());
                List<Integer> countryIds = CollectionUtils.convertList(areaCountryListByAreaIds, AreaCountryDTO::getCountryId);
                policyRespVO.setCountryIds(countryIds);
                policyRespVO.setRoomModelIds(policyDetailDO.getRoomModelIds());
                policyRespVO.setSurplusNum(policyDetailDO.getSurplusNum());
            }
        });
        return policyRespVOS;
    }

}