package com.usky.meeting.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.type.CollectionLikeType;
import com.usky.common.core.bean.CommonPage;
import com.usky.common.core.exception.BusinessException;
import com.usky.common.security.utils.SecurityUtils;
import com.usky.meeting.domain.*;
import com.usky.meeting.mapper.MeetingDeviceMapper;
import com.usky.meeting.mapper.MeetingRoomMapper;
import com.usky.meeting.repository.MeetingAttendeeRepository;
import com.usky.meeting.repository.MeetingDeviceRepository;
import com.usky.meeting.repository.MeetingInfoRepository;
import com.usky.meeting.repository.MeetingRoomRepository;
import com.usky.meeting.service.*;
import com.usky.common.mybatis.core.AbstractCrudService;
import com.usky.meeting.service.dto.DmMeetingRoomDto;
import com.usky.meeting.service.vo.MeetingRoomRequestVO;
import com.usky.meeting.service.vo.MeetingRoomReservationVO;
import lombok.RequiredArgsConstructor;
import org.apache.tomcat.jni.Local;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.math.BigInteger;
import java.sql.Timestamp;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * <p>
 * 会议室表 服务实现类
 * </p>
 *
 * @author zyj
 * @since 2024-03-08
 */
@Service
@RequiredArgsConstructor
public class MeetingRoomServiceImpl extends AbstractCrudService<MeetingRoomMapper, MeetingRoom> implements MeetingRoomService {

    @Autowired
    private MeetingRoomRepository dmMeetingRoomRepository;
    @Autowired
    private MeetingAttendeeRepository meetingAttendeeRepository;
    @Autowired
    private MeetingInfoService dmMeetingService;
    @Autowired
    private MeetingFloorService dmFloorService;
    @Autowired
    private MeetingDeviceRepository meetingDeviceRepository;
    @Autowired
    private MeetingInfoRepository meetingInfoRepository;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private MeetingDeviceMapper deviceMapper;

    @Override
    public Map<String, Object> FirstPageStatistic(String year) {
        Map<String, Object> map = new HashMap<>();
        Integer tenantId = SecurityUtils.getTenantId();
        Map<String, Object> roomSummary = dmMeetingRoomRepository.roomSummary(tenantId);
        map.put("roomSummary", roomSummary);
        Map<String, Object> meetingSummary = dmMeetingService.meetingSummary(tenantId);
        map.put("meetingSummary", meetingSummary);
        Map<String, Object> meetingSummaryByYear = dmMeetingService.meetingSummaryByYear(year, tenantId);
        map.put("meetingSummaryByYear", meetingSummaryByYear);

        return map;
    }

    @Override
    public CommonPage<MeetingRoom> dmMeetingRoomList(MeetingRoomRequestVO requestVO) {
        IPage<MeetingRoom> page = new Page<>(requestVO.getCurrent(), requestVO.getSize());
        LambdaQueryWrapper<MeetingRoom> queryWrapper = Wrappers.lambdaQuery();

        if (StringUtils.isNotBlank(requestVO.getFloorName())) {
            List<String> floorId = new ArrayList<>();
            QueryWrapper<MeetingFloor> query = Wrappers.query();
            query.select("floor_id").like("floor_name", requestVO.getFloorName())
                    .eq("tenant_id", SecurityUtils.getTenantId());
            List<Map<String, Object>> map = dmFloorService.listMaps(query);
            if (CollectionUtils.isNotEmpty(map)) {
                for (int i = 0; i < map.size(); i++) {
                    floorId.add(map.get(i).get("floor_id").toString());
                }
            }

            if (CollectionUtils.isNotEmpty(floorId)) {
                queryWrapper.like(StringUtils.isNotBlank(requestVO.getRoomName()), MeetingRoom::getRoomName, requestVO.getRoomName())
                        .in(MeetingRoom::getFloorId, floorId)
                        .eq(null != requestVO.getStatus(), MeetingRoom::getStatus, requestVO.getStatus())
                        .eq(null != requestVO.getRoomStatus(), MeetingRoom::getRoomStatus, requestVO.getRoomStatus())
                        .eq(MeetingRoom::getTenantId, SecurityUtils.getTenantId())
                        .orderByDesc(MeetingRoom::getRoomId);
            } else {
                queryWrapper.like(StringUtils.isNotBlank(requestVO.getRoomName()), MeetingRoom::getRoomName, requestVO.getRoomName())
                        .in(MeetingRoom::getFloorId, "")
                        .eq(null != requestVO.getStatus(), MeetingRoom::getStatus, requestVO.getStatus())
                        .eq(null != requestVO.getRoomStatus(), MeetingRoom::getRoomStatus, requestVO.getRoomStatus())
                        .eq(MeetingRoom::getTenantId, SecurityUtils.getTenantId())
                        .orderByDesc(MeetingRoom::getRoomId);
            }

        } else {
            queryWrapper.like(StringUtils.isNotBlank(requestVO.getRoomName()), MeetingRoom::getRoomName, requestVO.getRoomName())
                    .eq(null != requestVO.getStatus(), MeetingRoom::getStatus, requestVO.getStatus())
                    .eq(null != requestVO.getRoomStatus(), MeetingRoom::getRoomStatus, requestVO.getRoomStatus())
                    .eq(MeetingRoom::getTenantId, SecurityUtils.getTenantId())
                    .orderByDesc(MeetingRoom::getRoomId);
        }
        page = this.page(page, queryWrapper);
        if (CollectionUtils.isNotEmpty(page.getRecords())) {
            // 查询楼层信息和本地存储信息
            List<Long> floorIdList = new ArrayList<>();
            for (int i = 0; i < page.getRecords().size(); i++) {
                Long floorId1 = page.getRecords().get(i).getFloorId();
                if (!floorIdList.contains(floorId1)) {
                    floorIdList.add(floorId1);
                }
            }
            LambdaQueryWrapper<MeetingFloor> floorQuery = Wrappers.lambdaQuery();
            floorQuery.in(CollectionUtils.isNotEmpty(floorIdList), MeetingFloor::getFloorId, floorIdList)
                    .eq(MeetingFloor::getTenantId, SecurityUtils.getTenantId());
            List<MeetingFloor> floorList = dmFloorService.list(floorQuery);

            // 会议室匹配对应楼层信息和本地存储信息
            for (int i = 0; i < page.getRecords().size(); i++) {
                if (CollectionUtils.isNotEmpty(floorList)) {
                    Long frId = Long.valueOf(page.getRecords().get(i).getFloorId());
                    for (int j = 0; j < floorList.size(); j++) {
                        if (frId.equals(floorList.get(j).getFloorId())) {
                            page.getRecords().get(i).setMeetingFloor(floorList.get(j));
                            break;
                        }
                    }
                }
            }
        }

        return new CommonPage<>(page.getRecords(), page.getTotal(), requestVO.getSize(), requestVO.getCurrent());
    }

    @Override
    public List<MeetingRoom> MeetingRoomList(String domain) {
        LambdaQueryWrapper<MeetingRoom> queryWrapper = Wrappers.lambdaQuery();
        if (StringUtils.isNotBlank(domain)) {
            Integer tenantId = dmMeetingRoomRepository.getTenantIdByDomain(domain);
            queryWrapper.eq(MeetingRoom::getTenantId, tenantId);
        } else {
            queryWrapper.eq(MeetingRoom::getTenantId, SecurityUtils.getTenantId());
        }

        List<MeetingRoom> list = this.list(queryWrapper);

        return list;
    }

    @Override
    public void add(MeetingRoom meetingRoom) {
        if (checkNameUnique(meetingRoom)) {
            throw new BusinessException("新增会议室房间失败，" + meetingRoom.getRoomName() + "已经存在");
        }
        meetingRoom.setRoomStatus(0);
        meetingRoom.setReserveStatus(0);
        meetingRoom.setCreateBy(SecurityUtils.getUsername());
        meetingRoom.setCreateTime(LocalDateTime.now());
        meetingRoom.setIsApprove(0);
        meetingRoom.setTenantId(SecurityUtils.getTenantId());
        this.save(meetingRoom);
    }

    @Override
    public void edit(MeetingRoom meetingRoom) {
        if (checkNameUnique(meetingRoom)) {
            throw new BusinessException("修改会议室房间失败，" + meetingRoom.getRoomName() + "已经存在");
        }
        meetingRoom.setUpdateBy(SecurityUtils.getUsername());
        meetingRoom.setUpdateTime(LocalDateTime.now());

        this.updateById(meetingRoom);
    }

    @Override
    public void remove(Long roomId) {
        List<MeetingDevice> deviceList = meetingDeviceRepository.getDeviceListByRoomId(roomId);
        if (deviceList.size() > 0) {
            throw new BusinessException("会议室有绑定设备，不可删除");
        }
        List<MeetingInfo> meetingList = meetingInfoRepository.queryAllMeetingByRoomId(roomId);
        if (meetingList.size() > 0) {
            throw new BusinessException("有会议记录不可删除");
        }

        MeetingRoom one = this.getById(roomId);
        Optional.ofNullable(one).orElseThrow(() -> new BusinessException("该会议室房间不存在"));

        this.removeById(roomId);
    }

    @Override
    public Map<String, Object> attendee(Long meetingId, Long userId, String userName, String deviceCode) {
        Map<String, Object> map = new HashMap<>();
        Integer tenantId;

        if (StringUtils.isNotBlank(deviceCode)) {
            LambdaQueryWrapper<MeetingDevice> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(MeetingDevice::getDeviceCode, deviceCode);
            tenantId = deviceMapper.selectOne(queryWrapper).getTenantId();
        } else {
            tenantId = SecurityUtils.getTenantId();
        }

        map.put("userName", userName);
        List<MeetingAttendee> list = meetingAttendeeRepository.findMeetingAttendeeList(meetingId, userId, tenantId);
        if (org.springframework.util.CollectionUtils.isEmpty(list)) {
            map.put("status", "0");
            map.put("msg", "您当前没有需要参加的会议");
        } else {
            map.put("status", "1");
            map.put("msg", "验证成功");
        }
        return map;
    }

    @Override
    public List<DmMeetingRoomDto> getMeetingRoomReservationList(MeetingRoomReservationVO reservationVO) throws ParseException {
        List<DmMeetingRoomDto> list = new ArrayList<>();
        List<DmMeetingRoomDto> newDmMeetingRoomDtoList = new ArrayList<>();
        String meetingRoomName = reservationVO.getMeetingRoomName();
        Long meetingRoomId = reservationVO.getMeetingRoomId();
        String deviceCode = reservationVO.getDeviceCode();
        Integer tenantId;
        if (StringUtils.isNotBlank(deviceCode)) {
            LambdaQueryWrapper<MeetingDevice> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(MeetingDevice::getDeviceCode, reservationVO.getDeviceCode());
            tenantId = deviceMapper.selectOne(queryWrapper).getTenantId();
        } else {
            tenantId = SecurityUtils.getTenantId();
        }


        LambdaQueryWrapper<MeetingRoom> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(meetingRoomId != null, MeetingRoom::getRoomId, reservationVO.getMeetingRoomId())
                .like(StringUtils.isNotBlank(meetingRoomName), MeetingRoom::getRoomName, meetingRoomName)
                .eq(MeetingRoom::getTenantId, tenantId);
        List<MeetingRoom> list1 = this.list(queryWrapper);
        List<Long> floorIdList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(list1)) {
            for (int i = 0; i < list1.size(); i++) {
                if (!floorIdList.contains(list1.get(i).getFloorId())) {
                    floorIdList.add(list1.get(i).getFloorId());
                }
            }
            LambdaQueryWrapper<MeetingFloor> floorWrapper = Wrappers.lambdaQuery();
            floorWrapper.in(MeetingFloor::getFloorId, floorIdList)
                    .eq(MeetingFloor::getTenantId, tenantId);
            List<MeetingFloor> meetingFloorList = dmFloorService.list(floorWrapper);
            if (CollectionUtils.isNotEmpty(meetingFloorList)) {
                for (int i = 0; i < list1.size(); i++) {
                    DmMeetingRoomDto dmMeetingRoomDto = new DmMeetingRoomDto();
                    dmMeetingRoomDto.setRoomId(list1.get(i).getRoomId());
                    dmMeetingRoomDto.setRoomName(list1.get(i).getRoomName());
                    for (int j = 0; j < meetingFloorList.size(); j++) {
                        if (list1.get(i).getFloorId().equals(meetingFloorList.get(j).getFloorId())) {
                            dmMeetingRoomDto.setDmFloor(meetingFloorList.get(j));
                            break;
                        }
                    }
                    dmMeetingRoomDto.setDescription(list1.get(i).getDescription());
                    dmMeetingRoomDto.setImgPath(list1.get(i).getImgPath());
                    dmMeetingRoomDto.setCapacity(list1.get(i).getCapacity());
                    dmMeetingRoomDto.setPosition(list1.get(i).getPosition());
                    dmMeetingRoomDto.setMaintainer(list1.get(i).getMaintainer());
                    dmMeetingRoomDto.setContacts(list1.get(i).getContacts());
                    dmMeetingRoomDto.setRemark(list1.get(i).getRemark());
                    dmMeetingRoomDto.setRoomStatus(list1.get(i).getRoomStatus());
                    dmMeetingRoomDto.setReserveStatus(list1.get(i).getReserveStatus());
                    dmMeetingRoomDto.setStatus(list1.get(i).getStatus());
                    dmMeetingRoomDto.setEnvironmental(list1.get(i).getEnvironmental());
                    dmMeetingRoomDto.setLastUseTime(list1.get(i).getLastUseTime());
                    dmMeetingRoomDto.setIsApprove(list1.get(i).getIsApprove());
                    list.add(dmMeetingRoomDto);
                }
            }
        }
        if (!list.isEmpty()) {
            for (DmMeetingRoomDto dmMeetingRoomDto : list) {
                if (ObjectUtils.isEmpty(reservationVO.getDate())) {
                    reservationVO.setDate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                }
                JSONObject meetingRoomUsageByDayV2 = dmMeetingService.getMeetingRoomUsageByDayV2(dmMeetingRoomDto.getRoomId(), reservationVO.getDate(), tenantId);

                JSONArray dmMeeting = meetingRoomUsageByDayV2.getJSONArray("dmMeeting");
                dmMeetingRoomDto.setDmMeetingList(dmMeeting);

                dmMeetingRoomDto.setMeetingRoomUsage(meetingRoomUsageByDayV2.getJSONArray("timeRange"));
                List<Integer> monthList = dmMeetingService.getMeetingRoomUsageByMonth(dmMeetingRoomDto.getRoomId(), reservationVO.getDate(), tenantId);
                dmMeetingRoomDto.setMeetingRoomUsageMonth(monthList);

                newDmMeetingRoomDtoList.add(dmMeetingRoomDto);
            }
        }

        return newDmMeetingRoomDtoList;
    }

    @Override
    public MeetingRoom meetingRoomDetails(Long roomId) {
        // 查询会议室基础信息
        MeetingRoom meetingRoom = this.getById(roomId);

        // 楼层信息
        Long floorId = meetingRoom.getFloorId();
        MeetingFloor meetingFloor = dmFloorService.getById(floorId);

        // 会议室设备列表
        List<MeetingDevice> deviceList = meetingDeviceRepository.getDeviceListByRoomId(roomId);
        // 查询今天所有的会议
        List<MeetingInfo> meetingList = meetingInfoRepository.queryTodayMeetingByRoomId(roomId);

        LambdaQueryWrapper<SysUser> sysUserQuery = Wrappers.lambdaQuery();
        sysUserQuery.eq(SysUser::getTenantId, SecurityUtils.getTenantId());
        List<SysUser> userList = sysUserService.list(sysUserQuery);
        if (userList.size() <= 0) {
            throw new BusinessException("用户信息不能为空");
        }
        if (!ObjectUtil.isEmpty(meetingList)) {
            for (MeetingInfo dmMeeting : meetingList) {
                // 参会人员信息
                List<SysUser> attendeeUserList = new ArrayList<>();
                List<MeetingAttendee> attendeeList = meetingAttendeeRepository.findMeetingAttendeeList(dmMeeting.getMeetingId(), null, SecurityUtils.getTenantId());
                if (attendeeList.size() > 0) {
                    for (int i = 0; i < attendeeList.size(); i++) {
                        Long uid = attendeeList.get(i).getUserId();
                        for (int j = 0; j < userList.size(); j++) {
                            if (uid.equals(userList.get(j).getUserId())) {
                                attendeeUserList.add(userList.get(j));
                                break;
                            }
                        }
                    }
                }
                dmMeeting.setUsers(attendeeUserList);
                // 发起人信息
                for (int i = 0; i < userList.size(); i++) {
                    if (userList.get(i).getUserId().equals(Long.valueOf(dmMeeting.getInitiatorId()))) {
                        dmMeeting.setInitiatorUser(userList.get(i));
                        break;
                    }
                }

            }
        }

        meetingRoom.setMeetingFloor(meetingFloor);
        meetingRoom.setMeetingDevice(deviceList);
        meetingRoom.setMeetingInfo(meetingList);

        return meetingRoom;
    }

    public boolean checkNameUnique(MeetingRoom meetingRoom) {
        Long id = null == meetingRoom.getRoomId() ? -1 : meetingRoom.getRoomId();
        LambdaQueryWrapper<MeetingRoom> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(MeetingRoom::getRoomName, meetingRoom.getRoomName())
                .eq(MeetingRoom::getTenantId, SecurityUtils.getTenantId());
        MeetingRoom one = this.getOne(queryWrapper);
        return null != one && !Objects.equals(one.getRoomId(), id);

    }
}
