package com.njcn.rdms.module.project.dal.mysql.overtime;

import com.njcn.rdms.framework.common.pojo.PageResult;
import com.njcn.rdms.framework.mybatis.core.dataobject.BaseDO;
import com.njcn.rdms.framework.mybatis.core.mapper.BaseMapperX;
import com.njcn.rdms.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.njcn.rdms.module.project.controller.admin.overtime.vo.OvertimeApplicationPageReqVO;
import com.njcn.rdms.module.project.dal.dataobject.overtime.OvertimeApplicationDO;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.util.StringUtils;

import java.util.Collection;
import java.util.List;

@Mapper
public interface OvertimeApplicationMapper extends BaseMapperX<OvertimeApplicationDO> {

    default PageResult<OvertimeApplicationDO> selectMyPage(Long applicantId, OvertimeApplicationPageReqVO reqVO) {
        LambdaQueryWrapperX<OvertimeApplicationDO> queryWrapper = buildPageQuery(reqVO);
        queryWrapper.eq(OvertimeApplicationDO::getApplicantId, applicantId);
        queryWrapper.orderByDesc(OvertimeApplicationDO::getSubmitTime)
                .orderByDesc(OvertimeApplicationDO::getId);
        return selectPage(reqVO, queryWrapper);
    }

    default PageResult<OvertimeApplicationDO> selectMyPage(Collection<Long> applicantIds,
                                                           OvertimeApplicationPageReqVO reqVO,
                                                           Collection<String> allowedStatusCodes) {
        if (applicantIds == null || applicantIds.isEmpty() || (allowedStatusCodes != null && allowedStatusCodes.isEmpty())) {
            return new PageResult<>(List.of(), 0L);
        }
        LambdaQueryWrapperX<OvertimeApplicationDO> queryWrapper = buildPageQuery(reqVO);
        queryWrapper.in(OvertimeApplicationDO::getApplicantId, applicantIds);
        if (allowedStatusCodes != null) {
            queryWrapper.in(OvertimeApplicationDO::getStatusCode, allowedStatusCodes);
        }
        queryWrapper.orderByDesc(OvertimeApplicationDO::getSubmitTime)
                .orderByDesc(OvertimeApplicationDO::getId);
        return selectPage(reqVO, queryWrapper);
    }

    default PageResult<OvertimeApplicationDO> selectApprovalPage(Long approverId, OvertimeApplicationPageReqVO reqVO) {
        LambdaQueryWrapperX<OvertimeApplicationDO> queryWrapper = buildPageQuery(reqVO);
        queryWrapper.eq(OvertimeApplicationDO::getApproverId, approverId);
        queryWrapper.orderByDesc(OvertimeApplicationDO::getSubmitTime)
                .orderByDesc(OvertimeApplicationDO::getId);
        return selectPage(reqVO, queryWrapper);
    }

    default OvertimeApplicationDO selectByIdAndApplicantId(Long id, Long applicantId) {
        return selectOne(new LambdaQueryWrapperX<OvertimeApplicationDO>()
                .eq(OvertimeApplicationDO::getId, id)
                .eq(OvertimeApplicationDO::getApplicantId, applicantId));
    }

    default int updateByIdAndStatus(OvertimeApplicationDO update, Long id, String fromStatus) {
        return update(update, new LambdaQueryWrapperX<OvertimeApplicationDO>()
                .eq(OvertimeApplicationDO::getId, id)
                .eq(OvertimeApplicationDO::getStatusCode, fromStatus));
    }

    default int updateByIdAndStatusAndApplicantId(OvertimeApplicationDO update, Long id, String fromStatus,
                                                  Long applicantId) {
        return update(update, new LambdaQueryWrapperX<OvertimeApplicationDO>()
                .eq(OvertimeApplicationDO::getId, id)
                .eq(OvertimeApplicationDO::getStatusCode, fromStatus)
                .eq(OvertimeApplicationDO::getApplicantId, applicantId));
    }

    default int updateByIdAndStatusesAndApplicantId(OvertimeApplicationDO update, Long id,
                                                    Collection<String> fromStatuses, Long applicantId) {
        return update(update, new LambdaQueryWrapperX<OvertimeApplicationDO>()
                .eq(OvertimeApplicationDO::getId, id)
                .in(OvertimeApplicationDO::getStatusCode, fromStatuses)
                .eq(OvertimeApplicationDO::getApplicantId, applicantId));
    }

    private LambdaQueryWrapperX<OvertimeApplicationDO> buildPageQuery(OvertimeApplicationPageReqVO reqVO) {
        LambdaQueryWrapperX<OvertimeApplicationDO> queryWrapper = new LambdaQueryWrapperX<>();
        queryWrapper.likeIfPresent(OvertimeApplicationDO::getApplicantName, reqVO.getApplicantName())
                .eqIfPresent(OvertimeApplicationDO::getApproverId, reqVO.getApproverId())
                .likeIfPresent(OvertimeApplicationDO::getApproverName, reqVO.getApproverName())
                .eqIfPresent(OvertimeApplicationDO::getStatusCode, reqVO.getStatusCode())
                .betweenIfPresent(OvertimeApplicationDO::getOvertimeDate, reqVO.getOvertimeDate())
                .betweenIfPresent(BaseDO::getCreateTime, reqVO.getCreateTime());
        if (StringUtils.hasText(reqVO.getKeyword())) {
            queryWrapper.and(wrapper -> wrapper.like(OvertimeApplicationDO::getOvertimeReason, reqVO.getKeyword())
                    .or()
                    .like(OvertimeApplicationDO::getOvertimeContent, reqVO.getKeyword()));
        }
        return queryWrapper;
    }
}
