package com.xxfc.platform.vehicle.biz;

import com.github.wxiaoqi.security.common.biz.BaseBiz;
import com.github.wxiaoqi.security.common.exception.BaseException;
import com.xxfc.platform.vehicle.entity.Festival;
import com.xxfc.platform.vehicle.entity.VehicleModelHolidayPrice;
import com.xxfc.platform.vehicle.mapper.VehicleModelHolidayPriceMapper;
import com.xxfc.platform.vehicle.pojo.dto.VehicleModelHolidayPriceDTO;
import com.xxfc.platform.vehicle.pojo.dto.VehicleModelHolidayPriceFindDTO;
import com.xxfc.platform.vehicle.pojo.dto.VehicleModelHolidayPriceSaveDTO;
import com.xxfc.platform.vehicle.pojo.vo.VehicleModelHolidayPriceVo;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author libin
 * @version 1.0
 * @description
 * @data 2019/10/14 17:32
 */
@Transactional(rollbackFor = Exception.class)
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class VehicleModelHolidayPriceBiz extends BaseBiz<VehicleModelHolidayPriceMapper, VehicleModelHolidayPrice> {

    private final FestivalBiz festivalBiz;

    /**
     * 保存
     *
     * @param vehicleModelHolidayPriceSaveDTO
     * @param userId
     */
    public void addVehicleModelHolidayPrice(VehicleModelHolidayPriceSaveDTO vehicleModelHolidayPriceSaveDTO, Integer userId) {
        List<VehicleModelHolidayPrice> vehicleModelHolidayPriceList = new ArrayList<>();
        VehicleModelHolidayPrice vehicleModelHolidayPrice;

        List<Date> dates = vehicleModelHolidayPriceSaveDTO.getDate();
        for (Date date : dates) {
            vehicleModelHolidayPrice = new VehicleModelHolidayPrice();
            BeanUtils.copyProperties(vehicleModelHolidayPriceSaveDTO, vehicleModelHolidayPrice);
            date = Date.from(date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate().atStartOfDay(ZoneId.systemDefault()).toInstant());
            vehicleModelHolidayPrice.setFestivalDay(date);
            vehicleModelHolidayPriceList.add(vehicleModelHolidayPrice);
        }
        //编辑
        if (Objects.nonNull(vehicleModelHolidayPriceSaveDTO.getId())) {
            Example example = new Example(VehicleModelHolidayPrice.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("festivalId", vehicleModelHolidayPriceSaveDTO.getId());
            for (VehicleModelHolidayPrice modelHolidayPrice : vehicleModelHolidayPriceList) {
                modelHolidayPrice.setUpdUserId(userId);
                modelHolidayPrice.setUpdTime(new Date());
                mapper.updateByExample(modelHolidayPrice, example);
            }
        } else {
            Festival festival = new Festival();
            festival.setName(vehicleModelHolidayPriceSaveDTO.getFestival());
            festivalBiz.add(festival);
            for (VehicleModelHolidayPrice modelHolidayPrice : vehicleModelHolidayPriceList) {
                modelHolidayPrice.setCrtTime(new Date());
                modelHolidayPrice.setCrtUserId(userId);
                modelHolidayPrice.setFestivalId(festival.getId());
                mapper.insertSelective(modelHolidayPrice);
            }
        }
    }

    /**
     * @param multiple   倍数
     * @param freeDays   免费天数
     * @param configDate 设置的日期*月份
     */
    public void updateVehicleModelHolidayPrice(Double multiple, Integer freeDays, Date configDate) {
        VehicleModelHolidayPrice vehicleModelHolidayPrice = new VehicleModelHolidayPrice();
        vehicleModelHolidayPrice.setMultiple(multiple);
        vehicleModelHolidayPrice.setFreeDays(freeDays);
        Example example = new Example(VehicleModelHolidayPrice.class);
        Example.Criteria criteria = example.createCriteria();
        setCondtionDate(configDate, null, criteria);
        int effect = mapper.updateByExampleSelective(vehicleModelHolidayPrice, example);
        if (effect < 1) {
            throw new BaseException("车型节假日更新失败");
        }
    }

    /**
     * 按年 月 节假日 等条件查询
     *
     * @param vehicleModelHolidayPriceFindDTO
     * @return
     */
    public List<VehicleModelHolidayPriceVo> listVehicleModelHolidayPrice(VehicleModelHolidayPriceFindDTO vehicleModelHolidayPriceFindDTO) {
        List<VehicleModelHolidayPriceVo> vehicleModelHolidayPriceVos = new ArrayList<>();
        Example example = new Example(VehicleModelHolidayPrice.class);
        Example.Criteria criteria = example.createCriteria();
        Date date = null;
        if (StringUtils.isNotEmpty(vehicleModelHolidayPriceFindDTO.getDate()) && vehicleModelHolidayPriceFindDTO.getDate().trim().length() > 0) {
            date = Date.from(LocalDate.parse(vehicleModelHolidayPriceFindDTO.getDate()).atStartOfDay(ZoneId.systemDefault()).toInstant());
        }
        setCondtionDate(date, vehicleModelHolidayPriceFindDTO.getYear(), criteria);
        if (StringUtils.isNotEmpty(vehicleModelHolidayPriceFindDTO.getFestival()) && vehicleModelHolidayPriceFindDTO.getFestival().trim().length() > 0) {
            criteria.andLike("festival", String.format("%%%s%%", vehicleModelHolidayPriceFindDTO.getFestival()));
        }
        List<VehicleModelHolidayPrice> holidayPrices = mapper.selectByExample(example);
        if (CollectionUtils.isEmpty(holidayPrices)) {
            return vehicleModelHolidayPriceVos;
        }
        List<Integer> festivalIds = holidayPrices.stream().map(VehicleModelHolidayPrice::getFestivalId).collect(Collectors.toList());
        Map<Integer,Festival> festivalMap = festivalBiz.findFestivalsByIds(festivalIds);
        VehicleModelHolidayPriceVo vehicleModelHolidayPriceVo;
        for (VehicleModelHolidayPrice holidayPrice : holidayPrices) {
            vehicleModelHolidayPriceVo = new VehicleModelHolidayPriceVo();
            BeanUtils.copyProperties(holidayPrice, vehicleModelHolidayPriceVo);
            vehicleModelHolidayPriceVo.setFestival(festivalMap==null?"":festivalMap.get(holidayPrice.getFestivalId()).getName());
            vehicleModelHolidayPriceVos.add(vehicleModelHolidayPriceVo);
        }
        return vehicleModelHolidayPriceVos;
    }

    /**
     * 根据开始与结束时间查询
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public List<VehicleModelHolidayPriceDTO> findVehicleModelHolidayPriceByMonth(Date startDate, Date endDate) {
        List<VehicleModelHolidayPriceDTO> vehicleModelHolidayPriceDTOS = new ArrayList<>();
        Example example = new Example(VehicleModelHolidayPrice.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andBetween("festivalDay", startDate, endDate);
        List<VehicleModelHolidayPrice> modelHolidayPrices = mapper.selectByExample(example);
        if (CollectionUtils.isEmpty(modelHolidayPrices)) {
            return vehicleModelHolidayPriceDTOS;
        }
        List<Integer> festivalIds = modelHolidayPrices.stream().map(VehicleModelHolidayPrice::getFestivalId).collect(Collectors.toList());
        Map<Integer,Festival> festivalMap = festivalBiz.findFestivalsByIds(festivalIds);
        VehicleModelHolidayPriceDTO vehicleModelHolidayPriceDTO;
        for (VehicleModelHolidayPrice modelHolidayPrice : modelHolidayPrices) {
            vehicleModelHolidayPriceDTO = new VehicleModelHolidayPriceDTO();
            BeanUtils.copyProperties(modelHolidayPrice, vehicleModelHolidayPriceDTO);
            vehicleModelHolidayPriceDTO.setFestival(festivalMap==null?"":festivalMap.get(modelHolidayPrice.getFestivalId()).getName());
            vehicleModelHolidayPriceDTOS.add(vehicleModelHolidayPriceDTO);
        }
        return vehicleModelHolidayPriceDTOS;
    }

    /**
     * @param id
     * @return
     */
    public VehicleModelHolidayPriceSaveDTO findVehicleModelHolidayPriceFestivalId(Long id) {
        VehicleModelHolidayPriceSaveDTO modelHolidayPriceSaveDTO = new VehicleModelHolidayPriceSaveDTO();
        Example example = new Example(VehicleModelHolidayPrice.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("festivalId",id);
        List<VehicleModelHolidayPrice> vehicleModelHolidayPrices = mapper.selectByExample(example);
        if (CollectionUtils.isEmpty(vehicleModelHolidayPrices)) {
            throw new BaseException("数据不存在");
        }
        List<Date> dates = vehicleModelHolidayPrices.stream().map(VehicleModelHolidayPrice::getFestivalDay).collect(Collectors.toList());
        VehicleModelHolidayPrice vehicleModelHolidayPrice = vehicleModelHolidayPrices.get(0);
        BeanUtils.copyProperties(vehicleModelHolidayPrice, modelHolidayPriceSaveDTO);
        modelHolidayPriceSaveDTO.setDate(dates);
        return modelHolidayPriceSaveDTO;
    }

    /**
     * 设置查询条件日期
     *
     * @param conditionDate
     * @param criteria
     */
    private void setCondtionDate(Date conditionDate, Integer year, Example.Criteria criteria) {
        //开始日期
        Instant startInstant = null;
        //结束日期
        Instant endInstant = null;
        if (Objects.nonNull(year) && Objects.isNull(conditionDate)) {
            startInstant = LocalDate.of(year, 1, 1).atStartOfDay(ZoneId.systemDefault()).toInstant();
            endInstant = LocalDate.of(year, 12, 31).atStartOfDay(ZoneId.systemDefault()).toInstant();
        }
        if (Objects.nonNull(conditionDate)) {
            LocalDate localDate = conditionDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            startInstant = localDate.withDayOfMonth(1).atStartOfDay(ZoneId.systemDefault()).toInstant();
            LocalDate endLocalDate = localDate.with(TemporalAdjusters.lastDayOfMonth());
            endInstant = endLocalDate.atStartOfDay(ZoneId.systemDefault()).toInstant();
        }
        if (Objects.nonNull(startInstant) && Objects.nonNull(endInstant)) {
            criteria.andBetween("festivalDay", Date.from(startInstant), Date.from(endInstant));
        }
    }

}
