package org.dromara.project.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.project.domain.BusAttendance;
import org.dromara.project.domain.BusProject;
import org.dromara.project.domain.BusProjectTeam;
import org.dromara.project.domain.BusReissueCard;
import org.dromara.project.domain.enums.BusAttendanceClockStatusEnum;
import org.dromara.project.domain.enums.BusAttendanceCommuterEnum;
import org.dromara.project.domain.enums.BusOpinionStatusEnum;
import org.dromara.project.domain.enums.BusReviewStatusEnum;
import org.dromara.project.domain.dto.reissuecard.BusReissueCardManagerReviewReq;
import org.dromara.project.domain.dto.reissuecard.BusReissueCardQueryReq;
import org.dromara.project.domain.vo.reissuecard.BusReissueCardVo;
import org.dromara.project.mapper.BusReissueCardMapper;
import org.dromara.project.service.IBusAttendanceService;
import org.dromara.project.service.IBusProjectService;
import org.dromara.project.service.IBusProjectTeamService;
import org.dromara.project.service.IBusReissueCardService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 施工人员补卡申请Service业务层处理
 *
 * @author lcj
 * @date 2025-04-08
 */
@Service
public class BusReissueCardServiceImpl extends ServiceImpl<BusReissueCardMapper, BusReissueCard>
    implements IBusReissueCardService {

    @Resource
    private IBusProjectService projectService;

    @Resource
    private IBusProjectTeamService projectTeamService;

    @Resource
    private IBusAttendanceService attendanceService;

    /**
     * 查询施工人员补卡申请
     *
     * @param id 主键
     * @return 施工人员补卡申请
     */
    @Override
    public BusReissueCardVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询施工人员补卡申请列表
     *
     * @param req       查询条件
     * @param pageQuery 分页参数
     * @return 施工人员补卡申请分页列表
     */
    @Override
    public TableDataInfo<BusReissueCardVo> queryPageList(BusReissueCardQueryReq req, PageQuery pageQuery) {
        Page<BusReissueCard> result = this.page(pageQuery.build(), buildQueryWrapper(req));
        return TableDataInfo.build(this.getVoPage(result));
    }

    /**
     * 查询符合条件的施工人员补卡申请列表
     *
     * @param req 查询条件
     * @return 施工人员补卡申请列表
     */
    @Override
    public List<BusReissueCardVo> queryList(BusReissueCardQueryReq req) {
        LambdaQueryWrapper<BusReissueCard> lqw = buildQueryWrapper(req);
        return baseMapper.selectVoList(lqw);
    }

    /**
     * 管理员审核施工人员补卡申请
     *
     * @param req 管理员审核施工人员补卡申请
     * @return 是否审核成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean managerReview(BusReissueCardManagerReviewReq req) {
        Long id = req.getId();
        String managerOpinion = req.getManagerOpinion();
        // 判断该补卡记录是否存在
        BusReissueCard oldReissueCard = this.getById(id);
        if (oldReissueCard == null) {
            throw new ServiceException("施工人员补卡申请不存在", HttpStatus.NOT_FOUND);
        }
        // 如果已经审核过，则返回
        if (!BusOpinionStatusEnum.UNREAD.getValue().equals(managerOpinion)) {
            throw new ServiceException("该请假已审核，请勿重复操作", HttpStatus.BAD_REQUEST);
        }
        // 判断班组长是否审核通过
        String gangerOpinion = oldReissueCard.getGangerOpinion();
        if (!BusOpinionStatusEnum.PASS.getValue().equals(gangerOpinion)) {
            throw new ServiceException("请等待班组长审核通过后再进行操作", HttpStatus.BAD_REQUEST);
        }
        // todo 判断当前用户是否为项目管理员
        // 填充默认值，更新数据
        BusReissueCard reissueCard = new BusReissueCard();
        reissueCard.setId(id);
        reissueCard.setManagerOpinion(managerOpinion);
        reissueCard.setManagerExplain(req.getManagerExplain());
        reissueCard.setManagerTime(new Date());
        reissueCard.setRemark(req.getRemark());
        boolean result = this.updateById(reissueCard);
        if (!result) {
            throw new ServiceException("更新管理员审核操作失败", HttpStatus.ERROR);
        }
        // 更新考勤表记录
        BusAttendance oldAttendance = attendanceService.getById(oldReissueCard.getAttendanceId());
        if (oldAttendance == null) {
            throw new ServiceException("考勤记录不存在", HttpStatus.NOT_FOUND);
        }
        BusAttendance attendance = new BusAttendance();
        BusProject project = projectService.getById(oldReissueCard.getProjectId());
        // 根据补卡类型更新考勤时间
        String[] clockTime = project.getPunchRange().split(",");
        String reissueCardType = oldReissueCard.getReissueCardType();
        if (BusAttendanceCommuterEnum.CLOCKIN.getValue().equals(reissueCardType)) {
            // 拼接时间，获取项目的上班打卡时间
            Date date = DateUtils.combineDateAndTime(oldAttendance.getClockDate(), clockTime[0] + ":00");
            attendance.setClockTime(date);
        } else if (BusAttendanceCommuterEnum.CLOCKOUT.getValue().equals(reissueCardType)) {
            // 拼接时间，获取项目的下班打卡时间
            Date date = DateUtils.combineDateAndTime(oldAttendance.getClockDate(), clockTime[1] + ":00");
            attendance.setClockTime(date);
        }
        attendance.setId(oldReissueCard.getAttendanceId());
        attendance.setClockStatus(BusAttendanceClockStatusEnum.REISSUE.getValue());
        boolean updateAttendance = attendanceService.updateById(attendance);
        if (!updateAttendance) {
            throw new ServiceException("更新考勤记录失败", HttpStatus.ERROR);
        }
        return true;
    }

    /**
     * 校验并批量删除施工人员补卡申请信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            // TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 获取施工人员补卡申请视图对象
     *
     * @param reissueCard 施工人员补卡申请对象
     * @return 施工人员补卡申请视图对象
     */
    @Override
    public BusReissueCardVo getVo(BusReissueCard reissueCard) {
        // 对象转封装类
        BusReissueCardVo reissueCardVo = new BusReissueCardVo();
        if (reissueCard == null) {
            return reissueCardVo;
        }
        BeanUtils.copyProperties(reissueCard, reissueCardVo);
        // 获取班组信息
        Long teamId = reissueCard.getTeamId();
        if (teamId != null) {
            BusProjectTeam team = projectTeamService.lambdaQuery()
                .eq(BusProjectTeam::getId, teamId).select(BusProjectTeam::getTeamName).one();
            reissueCardVo.setTeamName(team.getTeamName());
        }
        // 添加审核状态
        String status = BusReviewStatusEnum.getEnumByOpinionStatus(reissueCard.getGangerOpinion(), reissueCard.getManagerOpinion());
        reissueCardVo.setStatus(status);
        return reissueCardVo;
    }

    /**
     * 获取施工人员补卡申请查询条件封装
     *
     * @param req 查询条件
     * @return 查询条件封装
     */
    @Override
    public LambdaQueryWrapper<BusReissueCard> buildQueryWrapper(BusReissueCardQueryReq req) {
        LambdaQueryWrapper<BusReissueCard> lqw = new LambdaQueryWrapper<>();
        if (req == null) {
            return lqw;
        }
        Long id = req.getId();
        Long userId = req.getUserId();
        String userName = req.getUserName();
        Long gangerId = req.getGangerId();
        String gangerName = req.getGangerName();
        String gangerOpinion = req.getGangerOpinion();
        String managerOpinion = req.getManagerOpinion();
        Long projectId = req.getProjectId();
        Long teamId = req.getTeamId();
        String reissueCardType = req.getReissueCardType();
        Long attendanceId = req.getAttendanceId();
        // 模糊查询
        lqw.like(StringUtils.isNotBlank(userName), BusReissueCard::getUserName, userName);
        lqw.like(StringUtils.isNotBlank(gangerName), BusReissueCard::getGangerName, gangerName);
        // 精确查询
        lqw.eq(ObjectUtils.isNotEmpty(id), BusReissueCard::getId, id);
        lqw.eq(ObjectUtils.isNotEmpty(userId), BusReissueCard::getUserId, userId);
        lqw.eq(ObjectUtils.isNotEmpty(gangerId), BusReissueCard::getGangerId, gangerId);
        lqw.eq(StringUtils.isNotBlank(gangerOpinion), BusReissueCard::getGangerOpinion, gangerOpinion);
        lqw.eq(StringUtils.isNotBlank(managerOpinion), BusReissueCard::getManagerOpinion, managerOpinion);
        lqw.eq(ObjectUtils.isNotEmpty(projectId), BusReissueCard::getProjectId, projectId);
        lqw.eq(ObjectUtils.isNotEmpty(teamId), BusReissueCard::getTeamId, teamId);
        lqw.eq(StringUtils.isNotBlank(reissueCardType), BusReissueCard::getReissueCardType, reissueCardType);
        lqw.eq(ObjectUtils.isNotEmpty(attendanceId), BusReissueCard::getAttendanceId, attendanceId);
        return lqw;
    }

    /**
     * 获取施工人员补卡申请分页对象视图
     *
     * @param reissueCardPage 施工人员补卡申请分页对象
     * @return 施工人员补卡申请分页对象视图
     */
    @Override
    public Page<BusReissueCardVo> getVoPage(Page<BusReissueCard> reissueCardPage) {
        List<BusReissueCard> reissueCardList = reissueCardPage.getRecords();
        Page<BusReissueCardVo> reissueCardVoPage = new Page<>(
            reissueCardPage.getCurrent(),
            reissueCardPage.getSize(),
            reissueCardPage.getTotal());
        if (CollUtil.isEmpty(reissueCardList)) {
            return reissueCardVoPage;
        }
        // 关联查询班组信息
        Set<Long> teamIdSet = reissueCardList.stream().map(BusReissueCard::getTeamId)
            .collect(Collectors.toSet());
        Map<Long, List<BusProjectTeam>> teamIdTeamMap = projectTeamService.listByIds(teamIdSet).stream()
            .collect(Collectors.groupingBy(BusProjectTeam::getId));
        List<BusReissueCardVo> reissueCardVoList = reissueCardList.stream().map(reissueCard -> {
            BusReissueCardVo reissueCardVo = new BusReissueCardVo();
            BeanUtils.copyProperties(reissueCard, reissueCardVo);
            // 关联班组信息
            Long teamId = reissueCard.getTeamId();
            String teamName = null;
            if (teamIdTeamMap.containsKey(teamId)) {
                teamName = projectTeamService.getVo(teamIdTeamMap.get(teamId).get(0)).getTeamName();
            }
            reissueCardVo.setTeamName(teamName);
            // 添加审核状态
            String status = BusReviewStatusEnum.getEnumByOpinionStatus(reissueCard.getGangerOpinion(), reissueCard.getManagerOpinion());
            reissueCardVo.setStatus(status);
            return reissueCardVo;
        }).toList();
        reissueCardVoPage.setRecords(reissueCardVoList);
        return reissueCardVoPage;
    }
}
