package com.xjrsoft.module.room.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.xjrsoft.common.enums.DeleteMark;
import com.xjrsoft.module.room.dto.AddRoomValueWeekDto;
import com.xjrsoft.module.room.dto.RoomValueWeekPageDto;
import com.xjrsoft.module.room.dto.UpdateRoomValueWeekDto;
import com.xjrsoft.module.room.entity.RoomValueWeek;
import com.xjrsoft.module.room.entity.RoomValueWeekItem;
import com.xjrsoft.module.room.entity.WfRoomStayOvernight;
import com.xjrsoft.module.room.mapper.RoomValueWeekItemMapper;
import com.xjrsoft.module.room.mapper.RoomValueWeekMapper;
import com.xjrsoft.module.room.mapper.WfRoomStayOvernightMapper;
import com.xjrsoft.module.room.service.IRoomValueWeekService;
import com.xjrsoft.module.room.vo.RoomValueWeekExcelVo;
import com.xjrsoft.module.room.vo.RoomValueWeekItemExcelVo;
import com.xjrsoft.module.room.vo.RoomValueWeekItemVo;
import com.xjrsoft.module.room.vo.RoomValueWeekPageVo;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
* @title: 宿管值班管理
* @Author dzx
* @Date: 2024-01-03
* @Version 1.0
*/
@Service
@AllArgsConstructor
public class RoomValueWeekServiceImpl extends MPJBaseServiceImpl<RoomValueWeekMapper, RoomValueWeek> implements IRoomValueWeekService {
    private final RoomValueWeekMapper roomValueWeekRoomValueWeekMapper;

    private final RoomValueWeekItemMapper roomValueWeekRoomValueWeekItemMapper;

    private final WfRoomStayOvernightMapper wfRoomStayOvernightMapper;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean add(AddRoomValueWeekDto dto) {
        RoomValueWeek roomValueWeek = BeanUtil.toBean(dto, RoomValueWeek.class);
        Integer maxSortCode = roomValueWeekRoomValueWeekMapper.getMaxSortCode();
        roomValueWeek.setSortCode(maxSortCode + 1);
        roomValueWeekRoomValueWeekMapper.insert(roomValueWeek);
        Integer ItemMaxSortCode = roomValueWeekRoomValueWeekItemMapper.getMaxSortCode();
        if(dto.getMaleUserId() != null){
            RoomValueWeekItem maleItem = new RoomValueWeekItem();
            maleItem.setRoomValueWeekId(roomValueWeek.getId());
            maleItem.setRoomType("男寝");
            maleItem.setPostName("宿管");
            maleItem.setUserId(dto.getMaleUserId());
            maleItem.setNumberPeople(dto.getMaleStudents());
            maleItem.setSortCode(ItemMaxSortCode + 1);
            roomValueWeekRoomValueWeekItemMapper.insert(maleItem);
        }
        if(dto.getFemaleUserId() != null){
            RoomValueWeekItem femaleItem = new RoomValueWeekItem();
            femaleItem.setRoomValueWeekId(roomValueWeek.getId());
            femaleItem.setRoomType("女寝");
            femaleItem.setPostName("宿管");
            femaleItem.setUserId(dto.getFemaleUserId());
            femaleItem.setNumberPeople(dto.getFemaleStudents());
            femaleItem.setSortCode(ItemMaxSortCode + 2);
            roomValueWeekRoomValueWeekItemMapper.insert(femaleItem);
        }
        if(dto.getInstructorUserId() != null){
            RoomValueWeekItem instructorItem = new RoomValueWeekItem();
            instructorItem.setRoomValueWeekId(roomValueWeek.getId());
            instructorItem.setPostName("教官");
            instructorItem.setUserId(dto.getInstructorUserId());
            instructorItem.setSortCode(ItemMaxSortCode + 3);
            roomValueWeekRoomValueWeekItemMapper.insert(instructorItem);
        }

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean update(RoomValueWeek roomValueWeek) {
        roomValueWeekRoomValueWeekMapper.updateById(roomValueWeek);
        //********************************* RoomValueWeekItem  增删改  开始 *******************************************/
        {
            // 查出所有子级的id
            List<RoomValueWeekItem> roomValueWeekItemList = roomValueWeekRoomValueWeekItemMapper.selectList(Wrappers.lambdaQuery(RoomValueWeekItem.class).eq(RoomValueWeekItem::getRoomValueWeekId, roomValueWeek.getId()).select(RoomValueWeekItem::getId));
            List<Long> roomValueWeekItemIds = roomValueWeekItemList.stream().map(RoomValueWeekItem::getId).collect(Collectors.toList());
            //原有子表单 没有被删除的主键
            List<Long> roomValueWeekItemOldIds = roomValueWeek.getRoomValueWeekItemList().stream().map(RoomValueWeekItem::getId).filter(Objects::nonNull).collect(Collectors.toList());
            //找到需要删除的id
            List<Long> roomValueWeekItemRemoveIds = roomValueWeekItemIds.stream().filter(item -> !roomValueWeekItemOldIds.contains(item)).collect(Collectors.toList());

            for (RoomValueWeekItem roomValueWeekItem : roomValueWeek.getRoomValueWeekItemList()) {
                //如果不等于空则修改
                if (roomValueWeekItem.getId() != null) {
                    roomValueWeekRoomValueWeekItemMapper.updateById(roomValueWeekItem);
                }
                //如果等于空 则新增
                else {
                    //已经不存在的id 删除
                    roomValueWeekItem.setRoomValueWeekId(roomValueWeek.getId());
                    roomValueWeekRoomValueWeekItemMapper.insert(roomValueWeekItem);
                }
            }
            //已经不存在的id 删除
            if(roomValueWeekItemRemoveIds.size() > 0){
                roomValueWeekRoomValueWeekItemMapper.deleteBatchIds(roomValueWeekItemRemoveIds);
            }
        }
        //********************************* RoomValueWeekItem  增删改  结束 *******************************************/

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delete(List<Long> ids) {
        roomValueWeekRoomValueWeekMapper.deleteBatchIds(ids);
        roomValueWeekRoomValueWeekItemMapper.delete(Wrappers.lambdaQuery(RoomValueWeekItem.class).in(RoomValueWeekItem::getRoomValueWeekId, ids));

        return true;
    }

    @Override
    public Page<RoomValueWeekPageVo> getPage(Page<RoomValueWeekPageDto> page, RoomValueWeekPageDto dto) {
        Page<RoomValueWeekPageVo> result = roomValueWeekRoomValueWeekItemMapper.getItemPage(page, dto);

        return result;
    }

    @Override
    public List<RoomValueWeekExcelVo> getList(RoomValueWeekPageDto dto) {
        List<RoomValueWeek> weekList = roomValueWeekRoomValueWeekMapper.selectList(
            new QueryWrapper<RoomValueWeek>().lambda()
            .le(ObjectUtil.isNotNull(dto.getEndTime()), RoomValueWeek::getEndTime, dto.getEndTime())
            .ge(ObjectUtil.isNotNull(dto.getStartTime()), RoomValueWeek::getStartTime, dto.getStartTime())
        );
        List<RoomValueWeekExcelVo> dataList = BeanUtil.copyToList(weekList, RoomValueWeekExcelVo.class);

        List<RoomValueWeekPageVo> allItemList = roomValueWeekRoomValueWeekItemMapper.getItemList(dto);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
        for (RoomValueWeekExcelVo weekExcelVo : dataList) {
            String title = sdf.format(weekExcelVo.getStartTime()) + "-" + sdf.format(weekExcelVo.getEndTime()) + "留宿情况及值班安排表";
            List<RoomValueWeekItemExcelVo> itemList = new ArrayList<>();
            itemList.add(new RoomValueWeekItemExcelVo(){{
                setColumn1(title);
                setColumn2(title);
                setColumn3(title);
                setColumn4(title);
            }});
            itemList.add(new RoomValueWeekItemExcelVo(){{
                setColumn1("留宿情况");
                setColumn2("留宿情况");
                setColumn3("宿舍值班人员安排");
                setColumn4("宿舍值班人员安排");
            }});

            int maleStudents = 0;
            int femaleStudents = 0;
            String maleHousemaster = "",femaleHousemaster = "", instructor = "";
            for (RoomValueWeekPageVo roomValueWeekPageVo : allItemList) {
                if(!roomValueWeekPageVo.getRoomValueWeekId().equals(weekExcelVo.getId())){
                    continue;
                }
                if("男寝".equals(roomValueWeekPageVo.getRoomType())){
                    maleStudents = roomValueWeekPageVo.getNumberPeople();
                    maleHousemaster = roomValueWeekPageVo.getUserName();
                }
                if("女寝".equals(roomValueWeekPageVo.getRoomType())){
                    femaleStudents = roomValueWeekPageVo.getNumberPeople();
                    femaleHousemaster = roomValueWeekPageVo.getUserName();
                }
                if("教官".equals(roomValueWeekPageVo.getPostName())){
                    instructor = roomValueWeekPageVo.getUserName();
                }
            }
            RoomValueWeekItemExcelVo maleHousemasterVo = new RoomValueWeekItemExcelVo();
            maleHousemasterVo.setColumn1("男生留宿情况");
            maleHousemasterVo.setColumn2("女生留宿情况");
            maleHousemasterVo.setColumn3("男生宿管");
            maleHousemasterVo.setColumn4(maleHousemaster);
            itemList.add(maleHousemasterVo);

            RoomValueWeekItemExcelVo femaleHousemasterVo = new RoomValueWeekItemExcelVo();
            femaleHousemasterVo.setColumn1(maleStudents + "");
            femaleHousemasterVo.setColumn2(femaleStudents + "");
            femaleHousemasterVo.setColumn3("女生宿管");
            femaleHousemasterVo.setColumn4(femaleHousemaster);
            itemList.add(femaleHousemasterVo);

            RoomValueWeekItemExcelVo instructorVo = new RoomValueWeekItemExcelVo();
            instructorVo.setColumn1(maleStudents + "");
            instructorVo.setColumn2(femaleStudents + "");
            instructorVo.setColumn3("教官");
            instructorVo.setColumn4(instructor);
            itemList.add(instructorVo);

            weekExcelVo.setItemList(itemList);
        }

        return dataList;
    }

    @Override
    public Boolean updateNumberPeople() {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        List<RoomValueWeek> weeks = roomValueWeekRoomValueWeekMapper.selectList(
            new QueryWrapper<RoomValueWeek>().lambda()
            .ge(RoomValueWeek::getEndTime, sdf.format(date))
            .le(RoomValueWeek::getStartTime, sdf.format(date))
        );

        for (RoomValueWeek week : weeks) {
            List<RoomValueWeekItem> roomValueWeekItems = roomValueWeekRoomValueWeekItemMapper.selectList(
                    new QueryWrapper<RoomValueWeekItem>().lambda().eq(RoomValueWeekItem::getRoomValueWeekId, week.getId())
            );
            for (RoomValueWeekItem roomValueWeekItem : roomValueWeekItems) {
                if("男寝".equals(roomValueWeekItem.getRoomType())){
                    Long maleStudents = wfRoomStayOvernightMapper.selectCount(
                            new QueryWrapper<WfRoomStayOvernight>().lambda()
                            .eq(WfRoomStayOvernight::getGenderName, "男")
                            .eq(WfRoomStayOvernight::getStatus, 1)
                            .eq(WfRoomStayOvernight::getDeleteMark, DeleteMark.NODELETE.getCode())
                            .le(WfRoomStayOvernight::getEndTime, sdf.format(week.getEndTime()))
                            .ge(WfRoomStayOvernight::getStartTime, sdf.format(week.getStartTime()))
                    );
                    roomValueWeekRoomValueWeekItemMapper.updateById(new RoomValueWeekItem(){{
                        setId(roomValueWeekItem.getId());
                        setNumberPeople(maleStudents.intValue());
                    }});
                }else if("女寝".equals(roomValueWeekItem.getRoomType())){
                    Long FemaleStudents = wfRoomStayOvernightMapper.selectCount(
                            new QueryWrapper<WfRoomStayOvernight>().lambda()
                                    .eq(WfRoomStayOvernight::getGenderName, "女")
                                    .eq(WfRoomStayOvernight::getStatus, 1)
                                    .eq(WfRoomStayOvernight::getDeleteMark, DeleteMark.NODELETE.getCode())
                                    .le(WfRoomStayOvernight::getEndTime, sdf.format(week.getEndTime()))
                                    .ge(WfRoomStayOvernight::getStartTime, sdf.format(week.getStartTime()))
                    );
                    roomValueWeekRoomValueWeekItemMapper.updateById(new RoomValueWeekItem(){{
                        setId(roomValueWeekItem.getId());
                        setNumberPeople(FemaleStudents.intValue());
                    }});
                }
            }
        }
        return null;
    }

    @Override
    public RoomValueWeekItemVo getItemInfo(Long id) {
        RoomValueWeekItem roomValueWeekItem = roomValueWeekRoomValueWeekItemMapper.selectById(id);
        RoomValueWeekItemVo itemVo = BeanUtil.toBean(roomValueWeekItem, RoomValueWeekItemVo.class);
        RoomValueWeek roomValueWeek = roomValueWeekRoomValueWeekMapper.selectById(roomValueWeekItem.getRoomValueWeekId());


        ZoneId zoneId = ZoneId.systemDefault();
        itemVo.setStartTime(ZonedDateTime.ofInstant(roomValueWeek.getStartTime().toInstant(), zoneId).toLocalDate());
        itemVo.setStartTime(ZonedDateTime.ofInstant(roomValueWeek.getEndTime().toInstant(), zoneId).toLocalDate());

        return itemVo;
    }

    @Override
    public Boolean updateItem(UpdateRoomValueWeekDto dto) {
        roomValueWeekRoomValueWeekItemMapper.updateById(new RoomValueWeekItem(){{
            setId(dto.getId());
            setUserId(dto.getUserId());
            setNumberPeople(dto.getNumberPeople());
        }});
        return true;
    }
}
