package com.jwipc.order.logic.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jwipc.exception.DaoException;
import com.jwipc.order.convert.AppointmentDayOffConvert;
import com.jwipc.order.dto.AppointmentDayOffBaseDTO;
import com.jwipc.order.dto.AppointmentPurchaseListDTO;
import com.jwipc.order.entity.AppointmentDayOff;
import com.jwipc.order.entity.AppointmentPurchase;
import com.jwipc.order.logic.AppointmentDayOffLogic;
import com.jwipc.order.model.po.AppointmentPurchasePO;
import com.jwipc.order.model.query.AppointmentDayOffQuery;
import com.jwipc.order.service.IAppointmentDayOffService;
import com.jwipc.page.PageUtil;
import com.jwipc.page.PageView;
import com.jwipc.security.LoginUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;

/**
 * <p>
 *
 * </p>
 *
 * @author wt
 * @version 1.0
 * @since 2024/3/6
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class AppointmentDayOffLogicImpl implements AppointmentDayOffLogic {

    private final IAppointmentDayOffService appointmentDayOffService;
    private final AppointmentDayOffConvert appointmentDayOffConvert;
    @Override
    public List<AppointmentDayOffBaseDTO> selectDataByQuery(AppointmentDayOffQuery query) {
        List<AppointmentDayOff> poList = appointmentDayOffService.selectListByPage(null,query);

        return appointmentDayOffConvert.POToDTOList(poList);
    }

    @Override
    public PageView selectListByPage(AppointmentDayOffQuery query) {
        final Page<AppointmentDayOff> dbPage = PageUtil.toPage(query);
        List<AppointmentDayOff> poList = appointmentDayOffService.selectListByPage(dbPage,query);

        List<AppointmentDayOffBaseDTO> dtoList = appointmentDayOffConvert.POToDTOList(poList);
        return PageUtil.getPV(dtoList, dbPage.getTotal());
    }

    @Override
    public Integer getTimeRange(Date startTime, String appointmentDate, List<AppointmentDayOffBaseDTO> dtoList) {
        int resultDate = Integer.parseInt(appointmentDate) - 1;
        DateTime endTime = DateUtil.offsetDay(startTime, resultDate);
        long dayOff = getDayOff(startTime, endTime, dtoList);
        resultDate += dayOff;
        startTime = endTime;
        while (dayOff > 0) {
            DateTime newEndTime = DateUtil.offsetDay(startTime, (int) dayOff);
            dayOff = getDayOff(startTime, newEndTime, dtoList);
            resultDate += dayOff;
            if (dayOff == 0) {
                break;
            }
            startTime = newEndTime;
        }
        return resultDate;
    }

    @Override
    public AppointmentDayOffBaseDTO selectById(String id) {
        AppointmentDayOff appointmentDayOff = appointmentDayOffService.getById(id);
        return appointmentDayOffConvert.entityToDTO(appointmentDayOff);
    }

    @Override
    public void createOrUpdate(AppointmentDayOffBaseDTO dayOffBaseDTO) {
        Long id = dayOffBaseDTO.getId();
        if (ObjectUtil.isNull(id)) {
            List<AppointmentDayOff> dayOffList = appointmentDayOffService.list(new LambdaQueryWrapper<AppointmentDayOff>()
                    .eq(AppointmentDayOff::getDay, dayOffBaseDTO.getDay()));
            if (CollectionUtil.isNotEmpty(dayOffList)) {
                throw new DaoException("日期已经存在");
            }

            dayOffBaseDTO.setCreateId(LoginUtil.getUserId());
            dayOffBaseDTO.setCreateTime(LocalDateTime.now());
        } else {
            dayOffBaseDTO.setUpdateId(LoginUtil.getUserId());
            dayOffBaseDTO.setUpdateTime(LocalDateTime.now());
        }
        AppointmentDayOff appointmentDayOff = appointmentDayOffConvert.dtoToEntity(dayOffBaseDTO);
        appointmentDayOffService.saveOrUpdate(appointmentDayOff);
    }

    @Override
    public void deleteById(Long id) {
        appointmentDayOffService.removeById(id);
    }

    private long getDayOff(Date startTime, Date endTime, List<AppointmentDayOffBaseDTO> dayOffArr) {
        if (CollectionUtil.isEmpty(dayOffArr)) {
            return 0;
        }
        return dayOffArr.stream().filter(t -> {
            Date day = Date.from(t.getDay().atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
            return DateUtil.isIn(day, startTime, endTime);
        }).count();
    }

}
