package com.yuchen.saas.park.service.service.fire.fight.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yuchen.saas.park.api.dto.fire.fight.FireFightShiftPlanReqDTO;
import com.yuchen.saas.park.api.dto.fire.fight.FireFightShiftPlanSubmitReqDTO;
import com.yuchen.saas.park.api.entity.fire.fight.SaasParkFireFightDutyStaff;
import com.yuchen.saas.park.api.entity.fire.fight.SaasParkFireFightShiftPlan;
import com.yuchen.saas.park.api.enums.inspect.WeekEnum;
import com.yuchen.saas.park.api.vo.fire.fight.FireFightShiftDutyInfoVO;
import com.yuchen.saas.park.api.vo.fire.fight.FireFightShiftPlanVO;
import com.yuchen.saas.park.service.mapper.fire.fight.SaasParkFireFightShiftPlanMapper;
import com.yuchen.saas.park.service.service.fire.fight.ISaasParkFireFightDutyStaffService;
import com.yuchen.saas.park.service.service.fire.fight.ISaasParkFireFightShiftPlanService;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.nest.springwrap.core.log.exception.ServiceException;
import org.nest.springwrap.core.mp.base.BaseEntity;
import org.nest.springwrap.core.mp.base.BaseServiceImpl;
import org.nest.springwrap.core.secure.ContextUser;
import org.nest.springwrap.core.secure.utils.AuthUtil;
import org.nest.springwrap.core.tool.utils.Func;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 消防排班计划 服务实现类
 * </p>
 *
 * @author zhouhanwei
 * @since 2024-04-29
 */
@Service
@RequiredArgsConstructor
public class SaasParkFireFightShiftPlanServiceImpl extends BaseServiceImpl<SaasParkFireFightShiftPlanMapper, SaasParkFireFightShiftPlan> implements ISaasParkFireFightShiftPlanService {

//    private final IOrgUserClient iOrgUserClient;

    private final ISaasParkFireFightDutyStaffService iSaasParkFireFightDutyStaffService;

    @Override
    public List<FireFightShiftPlanVO> findFireFightShiftPlanList(FireFightShiftPlanReqDTO reqDTO) {
        // 赋值数据
        LambdaQueryWrapper<SaasParkFireFightShiftPlan> lambdaWrapper = Wrappers.lambdaQuery();
        lambdaWrapper.eq(SaasParkFireFightShiftPlan::getCustomerId, reqDTO.getCustomerId());
        lambdaWrapper.eq(Func.isNotEmpty(reqDTO.getProjectId()), SaasParkFireFightShiftPlan::getProjectId, reqDTO.getProjectId());
        List<SaasParkFireFightShiftPlan> fireFightShiftPlanList = list(lambdaWrapper);
        // 返回数据
        List<FireFightShiftPlanVO> resultList = new ArrayList<>();
        if (CollUtil.isEmpty(fireFightShiftPlanList)) {
            return resultList;
        }
        // 获取所有的值班人员列表
        List<Long> staffIdAllList = new ArrayList<>();
        for (SaasParkFireFightShiftPlan shiftPlan : fireFightShiftPlanList) {
            List<Long> mondayIds = Arrays.stream(shiftPlan.getMonday().split(",")).map(Long::parseLong).collect(Collectors.toList());
            List<Long> tuesdayIds = Arrays.stream(shiftPlan.getTuesday().split(",")).map(Long::parseLong).collect(Collectors.toList());
            List<Long> wednesdayIds = Arrays.stream(shiftPlan.getWednesday().split(",")).map(Long::parseLong).collect(Collectors.toList());
            List<Long> thursdayIds = Arrays.stream(shiftPlan.getThursday().split(",")).map(Long::parseLong).collect(Collectors.toList());
            List<Long> fridayIds = Arrays.stream(shiftPlan.getFriday().split(",")).map(Long::parseLong).collect(Collectors.toList());
            List<Long> saturdayIds = Arrays.stream(shiftPlan.getSaturday().split(",")).map(Long::parseLong).collect(Collectors.toList());
            List<Long> sundayIds = Arrays.stream(shiftPlan.getSunday().split(",")).map(Long::parseLong).collect(Collectors.toList());
            staffIdAllList.addAll(mondayIds);
            staffIdAllList.addAll(tuesdayIds);
            staffIdAllList.addAll(wednesdayIds);
            staffIdAllList.addAll(thursdayIds);
            staffIdAllList.addAll(fridayIds);
            staffIdAllList.addAll(saturdayIds);
            staffIdAllList.addAll(sundayIds);
        }
        // 获取所有人员数据
//        List<NestOrgUser> orgUserList = iOrgUserClient.findOrgUserListByIds(orgUserAllList.stream().distinct().collect(Collectors.toList())).getData();
//        Map<Long, String> orgUserMap = orgUserList.stream().collect(Collectors.toMap(BaseEntity::getId, NestOrgUser::getName));
        List<SaasParkFireFightDutyStaff> staffList = iSaasParkFireFightDutyStaffService.listByIds(staffIdAllList);
        Map<Long, String> staffMap = staffList.stream().collect(Collectors.toMap(BaseEntity::getId, SaasParkFireFightDutyStaff::getOrgUserName));
        for (SaasParkFireFightShiftPlan shiftPlan : fireFightShiftPlanList) {
            FireFightShiftPlanVO vo = new FireFightShiftPlanVO();
            BeanUtil.copyProperties(shiftPlan, vo);
            vo.setMonday(setPeopleNamesValue(staffMap, vo.getMonday()));
            vo.setTuesday(setPeopleNamesValue(staffMap, vo.getTuesday()));
            vo.setWednesday(setPeopleNamesValue(staffMap, vo.getWednesday()));
            vo.setThursday(setPeopleNamesValue(staffMap, vo.getThursday()));
            vo.setFriday(setPeopleNamesValue(staffMap, vo.getFriday()));
            vo.setSaturday(setPeopleNamesValue(staffMap, vo.getSaturday()));
            vo.setSunday(setPeopleNamesValue(staffMap, vo.getSunday()));
            resultList.add(vo);
        }
        return resultList;
    }

    private String setPeopleNamesValue(Map<Long, String> staffMap, String staffIds) {
        List<String> orgUserNames = new ArrayList<>();
        List<Long> staffIdList = Arrays.stream(staffIds.split(",")).map(Long::parseLong).collect(Collectors.toList());
        for (Long staffId : staffIdList) {
            orgUserNames.add(staffMap.get(staffId));
        }
        return CollUtil.join(orgUserNames, ",");
    }

    private List<FireFightShiftPlanVO.StaffData> setPeopleNamesValueList(Map<Long, String> staffMap, String staffIds) {
        List<FireFightShiftPlanVO.StaffData> staffDataList = new ArrayList<>();
        List<Long> staffIdList = Arrays.stream(staffIds.split(",")).map(Long::parseLong).collect(Collectors.toList());
        for (Long staffId : staffIdList) {
            FireFightShiftPlanVO.StaffData staffData = new FireFightShiftPlanVO.StaffData();
            staffData.setStaffId(staffId);
            staffData.setStaffName(staffMap.get(staffId));
            staffDataList.add(staffData);
        }
        return staffDataList;
    }

    @Override
    public FireFightShiftPlanVO getFireFightShiftPlan(Long shiftPlanId) {
        FireFightShiftPlanVO vo = new FireFightShiftPlanVO();
        SaasParkFireFightShiftPlan saasParkFireFightShiftPlan = getById(shiftPlanId);
        if (Objects.isNull(saasParkFireFightShiftPlan)) {
            throw new ServiceException("班次计划数据不存在");
        }
        BeanUtil.copyProperties(saasParkFireFightShiftPlan, vo);
        List<Long> staffIdAllList = new ArrayList<>();
        List<Long> mondayIds = Arrays.stream(vo.getMonday().split(",")).map(Long::parseLong).collect(Collectors.toList());
        List<Long> tuesdayIds = Arrays.stream(vo.getTuesday().split(",")).map(Long::parseLong).collect(Collectors.toList());
        List<Long> wednesdayIds = Arrays.stream(vo.getWednesday().split(",")).map(Long::parseLong).collect(Collectors.toList());
        List<Long> thursdayIds = Arrays.stream(vo.getThursday().split(",")).map(Long::parseLong).collect(Collectors.toList());
        List<Long> fridayIds = Arrays.stream(vo.getFriday().split(",")).map(Long::parseLong).collect(Collectors.toList());
        List<Long> saturdayIds = Arrays.stream(vo.getSaturday().split(",")).map(Long::parseLong).collect(Collectors.toList());
        List<Long> sundayIds = Arrays.stream(vo.getSunday().split(",")).map(Long::parseLong).collect(Collectors.toList());
        staffIdAllList.addAll(mondayIds);
        staffIdAllList.addAll(tuesdayIds);
        staffIdAllList.addAll(wednesdayIds);
        staffIdAllList.addAll(thursdayIds);
        staffIdAllList.addAll(fridayIds);
        staffIdAllList.addAll(saturdayIds);
        staffIdAllList.addAll(sundayIds);
        List<SaasParkFireFightDutyStaff> staffList = iSaasParkFireFightDutyStaffService.listByIds(staffIdAllList);
        Map<Long, String> staffMap = staffList.stream().collect(Collectors.toMap(BaseEntity::getId, SaasParkFireFightDutyStaff::getOrgUserName));
        vo.setMondayList(setPeopleNamesValueList(staffMap, vo.getMonday()));
        vo.setTuesdayList(setPeopleNamesValueList(staffMap, vo.getTuesday()));
        vo.setWednesdayList(setPeopleNamesValueList(staffMap, vo.getWednesday()));
        vo.setThursdayList(setPeopleNamesValueList(staffMap, vo.getThursday()));
        vo.setFridayList(setPeopleNamesValueList(staffMap, vo.getFriday()));
        vo.setSaturdayList(setPeopleNamesValueList(staffMap, vo.getSaturday()));
        vo.setSundayList(setPeopleNamesValueList(staffMap, vo.getSunday()));
        return vo;
    }

    @Override
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public Boolean addFireFightShiftPlan(FireFightShiftPlanSubmitReqDTO reqDTO) {
        ContextUser contextUser = AuthUtil.getUser();
        if (Objects.isNull(contextUser)) {
            throw new ServiceException("用户不存在");
        }
        if (StrUtil.equals(reqDTO.getStartTime(), reqDTO.getEndTime())) {
            throw new ServiceException("开始时段不能等于结束时段");
        }
        // 判断时间有无重叠
        verifyTimeOverlap(contextUser, reqDTO);
        SaasParkFireFightShiftPlan saasParkFireFightShiftPlan = new SaasParkFireFightShiftPlan();
        BeanUtil.copyProperties(reqDTO, saasParkFireFightShiftPlan);
        // 判断班次名称有无重复
        saasParkFireFightShiftPlan.setCustomerId(contextUser.getCustomerManageId());
        saasParkFireFightShiftPlan.setCreateOrgUser(AuthUtil.getUser().getOrgUserId());
        validRepeat(saasParkFireFightShiftPlan);
        return save(saasParkFireFightShiftPlan);
    }

    @Override
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public Boolean editFireFightShiftPlan(FireFightShiftPlanSubmitReqDTO reqDTO) {
        ContextUser contextUser = AuthUtil.getUser();
        if (Objects.isNull(contextUser)) {
            throw new ServiceException("用户不存在");
        }
        if (StrUtil.equals(reqDTO.getStartTime(), reqDTO.getEndTime())) {
            throw new ServiceException("开始时段不能等于结束时段");
        }
        SaasParkFireFightShiftPlan saasParkFireFightShiftPlan = getById(reqDTO.getId());
        if (Objects.isNull(saasParkFireFightShiftPlan)) {
            throw new ServiceException("班次计划数据不存在");
        }
        // 判断时间有无重叠
        verifyTimeOverlap(contextUser, reqDTO);
        BeanUtil.copyProperties(reqDTO, saasParkFireFightShiftPlan);
        // 判断班次名称有无重复
        saasParkFireFightShiftPlan.setCustomerId(contextUser.getCustomerManageId());
        saasParkFireFightShiftPlan.setCreateOrgUser(AuthUtil.getUser().getOrgUserId());
        validRepeat(saasParkFireFightShiftPlan);
        return updateById(saasParkFireFightShiftPlan);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteFireFightShiftPlan(Long shiftPlanId) {
        SaasParkFireFightShiftPlan saasParkFireFightShiftPlan = getById(shiftPlanId);
        if (Objects.isNull(saasParkFireFightShiftPlan)) {
            throw new ServiceException("班次计划数据不存在");
        }
        return removeById(shiftPlanId);
    }

    @Override
    @SneakyThrows
    public List<FireFightShiftDutyInfoVO> getFireFightShiftDutyInfo(FireFightShiftPlanReqDTO reqDTO) {
        ContextUser contextUser = AuthUtil.getUser();
        if (Objects.isNull(contextUser)) {
            throw new ServiceException("用户不存在");
        }
        // 获取当前班次
        LambdaQueryWrapper<SaasParkFireFightShiftPlan> lambdaWrapper = Wrappers.lambdaQuery();
        lambdaWrapper.eq(SaasParkFireFightShiftPlan::getCustomerId, contextUser.getCustomerManageId());
        lambdaWrapper.eq(SaasParkFireFightShiftPlan::getProjectId, reqDTO.getProjectId());
        List<SaasParkFireFightShiftPlan> fireFightShiftPlanList = list(lambdaWrapper);
        if (CollUtil.isEmpty(fireFightShiftPlanList)) {
            throw new ServiceException("当前无值班信息");
        }
        // 根据当前时间获取对应班次
        SimpleDateFormat format = new SimpleDateFormat("HH:mm");
        Date newTime = format.parse(format.format(new Date()));
        SaasParkFireFightShiftPlan resultShiftPlan = null;
        for (SaasParkFireFightShiftPlan shiftPlan : fireFightShiftPlanList) {
            Date start = format.parse(shiftPlan.getStartTime());
            Date end = format.parse(shiftPlan.getEndTime());
            if (newTime.equals(start)) {
                resultShiftPlan = shiftPlan;
                break;
            }
            if (newTime.equals(end)) {
                resultShiftPlan = shiftPlan;
                break;
            }
            if (newTime.after(start) && newTime.before(end)) {
                resultShiftPlan = shiftPlan;
                break;
            }
        }
        if (Objects.isNull(resultShiftPlan)) {
            throw new ServiceException("当前无值班信息");
        }
        // 判断当前是周几获取对应人员
        List<Long> staffIdList = new ArrayList<>();
        LocalDate newDate = LocalDate.now();
        WeekEnum weekEnum = WeekEnum.getEnumByCode(newDate.getDayOfWeek().name());
        switch (weekEnum) {
            case MONDAY:
                if (Func.isNotEmpty(resultShiftPlan.getMonday())) {
                    staffIdList = Arrays.stream(resultShiftPlan.getMonday().split(","))
                            .map(Long::parseLong).collect(Collectors.toList());
                }
                break;
            case TUESDAY:
                if (Func.isNotEmpty(resultShiftPlan.getTuesday())) {
                    staffIdList = Arrays.stream(resultShiftPlan.getTuesday().split(","))
                            .map(Long::parseLong).collect(Collectors.toList());
                }
                break;
            case WEDNESDAY:
                if (Func.isNotEmpty(resultShiftPlan.getWednesday())) {
                    staffIdList = Arrays.stream(resultShiftPlan.getWednesday().split(","))
                            .map(Long::parseLong).collect(Collectors.toList());
                }
                break;
            case THURSDAY:
                if (Func.isNotEmpty(resultShiftPlan.getThursday())) {
                    staffIdList = Arrays.stream(resultShiftPlan.getThursday().split(","))
                            .map(Long::parseLong).collect(Collectors.toList());
                }
                break;
            case FRIDAY:
                if (Func.isNotEmpty(resultShiftPlan.getFriday())) {
                    staffIdList = Arrays.stream(resultShiftPlan.getFriday().split(","))
                            .map(Long::parseLong).collect(Collectors.toList());
                }
                break;
            case SATURDAY:
                if (Func.isNotEmpty(resultShiftPlan.getSaturday())) {
                    staffIdList = Arrays.stream(resultShiftPlan.getSaturday().split(","))
                            .map(Long::parseLong).collect(Collectors.toList());
                }
                break;
            case SUNDAY:
                if (Func.isNotEmpty(resultShiftPlan.getSunday())) {
                    staffIdList = Arrays.stream(resultShiftPlan.getSunday().split(","))
                            .map(Long::parseLong).collect(Collectors.toList());
                }
                break;
        }
        if (CollUtil.isEmpty(staffIdList)) {
            throw new ServiceException("当前无值班人员");
        }
        List<FireFightShiftDutyInfoVO> resultList = new ArrayList<>();
//        List<NestOrgUser> orgUserList = iOrgUserClient.findOrgUserListByIds(orgUserIdList.stream().distinct().collect(Collectors.toList())).getData();
//        Map<Long, NestOrgUser> nestOrgUserMap = orgUserList.stream().collect(Collectors.toMap(NestOrgUser::getId, v -> v, (v1, v2) -> v2));
        List<SaasParkFireFightDutyStaff> staffList = iSaasParkFireFightDutyStaffService.listByIds(staffIdList);
        Map<Long, SaasParkFireFightDutyStaff> staffMap = staffList.stream().collect(Collectors.toMap(BaseEntity::getId, v -> v, (v1, v2) -> v2));
        for (Long staffId : staffIdList) {
            FireFightShiftDutyInfoVO vo = new FireFightShiftDutyInfoVO();
            vo.setStaffId(staffId);
            SaasParkFireFightDutyStaff staff = staffMap.get(staffId);
            if (Objects.nonNull(staff)) {
                vo.setOrgUserId(staff.getOrgUserId());
                vo.setJobNo(staff.getJobNo());
                vo.setPosition(staff.getPosition());
                vo.setOrgUserName(staff.getOrgUserName());
                vo.setFaceImg(staff.getFaceImg());
                vo.setPhone(staff.getPhone());
            }
            resultList.add(vo);
        }
        return resultList;
    }

    private void validRepeat(SaasParkFireFightShiftPlan saasParkFireFightShiftPlan) {
        int count = count(new LambdaQueryWrapper<SaasParkFireFightShiftPlan>()
                .eq(SaasParkFireFightShiftPlan::getShiftName, saasParkFireFightShiftPlan.getShiftName())
                .eq(SaasParkFireFightShiftPlan::getCustomerId, saasParkFireFightShiftPlan.getCustomerId())
                .eq(SaasParkFireFightShiftPlan::getProjectId, saasParkFireFightShiftPlan.getProjectId())
                .notIn(Objects.nonNull(saasParkFireFightShiftPlan.getId()), BaseEntity::getId, saasParkFireFightShiftPlan.getId()));
        if (count > 0) {
            throw new ServiceException("班次编号不能重复");
        }
    }

    private void verifyTimeOverlap(ContextUser contextUser, FireFightShiftPlanSubmitReqDTO reqDTO) throws ParseException {
        FireFightShiftPlanReqDTO planReqDTO = new FireFightShiftPlanReqDTO();
        planReqDTO.setCustomerId(contextUser.getCustomerManageId());
        planReqDTO.setProjectId(reqDTO.getProjectId());
        List<FireFightShiftPlanVO> findFireFightShiftPlanList = findFireFightShiftPlanList(planReqDTO);
        if (CollUtil.isNotEmpty(findFireFightShiftPlanList)) {
            for (FireFightShiftPlanVO vo : findFireFightShiftPlanList) {
                if (vo.getId().equals(reqDTO.getId())) {
                    continue;
                }
                // 判断时间有无重叠
                verifyTimeOverlap(reqDTO.getStartTime(), reqDTO.getEndTime(), vo.getStartTime(), vo.getEndTime());
            }
        }
    }

    /**
     * 判断时间段有无重叠
     */
    private void verifyTimeOverlap(String startOne, String endOne, String startTwo, String endTwo) throws ParseException {
        SimpleDateFormat format = new SimpleDateFormat("HH:mm");

        // 定义第一个时间段
        Date start1 = format.parse(startOne);
        Date end1 = format.parse(endOne);

        // 定义第二个时间段
        Date start2 = format.parse(startTwo);
        Date end2 = format.parse(endTwo);

        // 判断两个时间段是否有重叠
        if (start1.before(end1) && start2.before(end2)) {
            // 2个时间段都不跨天
            if (end1.after(start2) && start1.before(end2)) {
                throw new ServiceException("时间段重叠。");
            }
        } else if (start1.after(end1) && start2.after(end2)) {
            // 如果2个时间段都跨天，那么它们一定重叠
            throw new ServiceException("时间段重叠了。");
        } else if (start1.after(end1) || start2.before(end2)) {
            // 第一个时间跨天
            if (start2.before(start1) && start2.before(end1)) {
                throw new ServiceException("时间段重叠了。");
            }
        } else if (start1.before(end1) || start2.after(end2)) {
            // 第二个时间跨天
            if (start1.before(start2) && start1.before(end2)) {
                throw new ServiceException("时间段重叠了。");
            }
        }
    }


}
