package cn.iocoder.yudao.module.system.dal.mysql.user;

import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
import cn.iocoder.yudao.module.system.controller.admin.laborcontract.vo.LaborContractPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.laborcontract.vo.LaborContractRespVO;
import cn.iocoder.yudao.module.system.controller.admin.user.dto.UserPageDTO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.factoryUser.FactoryUserPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.*;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.time.LocalDate;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

@Mapper
public interface AdminUserMapper extends BaseMapperX<AdminUserDO> {

    default AdminUserDO sgetByOpenId(String openId) {
        return selectOne(AdminUserDO::getOpenId, openId);
    }

    default AdminUserDO selectByUsername(String username) {
        return selectOne(AdminUserDO::getUsername, username);
    }

    default AdminUserDO selectByEmail(String email) {
        return selectOne(AdminUserDO::getEmail, email);
    }

    default AdminUserDO selectByMobile(String mobile) {
        return selectOne(AdminUserDO::getMobile, mobile);
    }

    default PageResult<AdminUserDO> selectPage(UserPageReqVO reqVO, Collection<Long> deptIds) {
        return selectPage(reqVO, new LambdaQueryWrapperX<AdminUserDO>()
                .likeIfPresent(AdminUserDO::getUsername, reqVO.getUsername())
                .likeIfPresent(AdminUserDO::getMobile, reqVO.getMobile())
                .likeIfPresent(AdminUserDO::getNickname, reqVO.getNickName())
                .eqIfPresent(AdminUserDO::getStatus, reqVO.getStatus())
                .betweenIfPresent(AdminUserDO::getCreateTime, reqVO.getCreateTime())
                .inIfPresent(AdminUserDO::getDeptId, deptIds)
                .eq(AdminUserDO::getUserType, 1)    //查询公司用户
                .orderByDesc(AdminUserDO::getId));
    }

    default PageResult<AdminUserDO> selectFactoryUserPage(FactoryUserPageReqVO reqVO, Long deptId) {

        return selectPage(reqVO, new LambdaQueryWrapperX<AdminUserDO>()
                .likeIfPresent(AdminUserDO::getNickname, reqVO.getNickname())
                .eqIfPresent(AdminUserDO::getDeptId, deptId)
                .eq(AdminUserDO::getUserType, 2)
                .orderByDesc(AdminUserDO::getId));
    }

    default List<AdminUserDO> selectListByNickname(String nickname) {
        return selectList(new LambdaQueryWrapperX<AdminUserDO>().like(AdminUserDO::getNickname, nickname));
    }

    default List<AdminUserDO> selectListByStatus(Integer userType, Integer status) {
        return selectList(new LambdaQueryWrapperX<AdminUserDO>()
                .eq(AdminUserDO::getStatus, status)
                .eqIfPresent(AdminUserDO::getUserType, userType));
    }

    default List<AdminUserDO> selectListByDeptIds(Collection<Long> deptIds, Integer status) {

        return selectList(new LambdaQueryWrapperX<AdminUserDO>()
                .in(AdminUserDO::getDeptId, deptIds)
                .eq(AdminUserDO::getUserType, 1)
                .eqIfPresent(AdminUserDO::getStatus, status));
    }

    default List<AdminUserDO> selectListByDeptId(Long deptId, Long userId) {
        return selectList(new LambdaQueryWrapperX<AdminUserDO>()
                .eq(AdminUserDO::getDeptId, deptId)
                .ne(AdminUserDO::getId, userId)
                .eq(AdminUserDO::getUserType, 1)
                .eq(AdminUserDO::getStatus, CommonStatusEnum.ENABLE.getStatus()));
    }

    void emptyOpenId(@Param("openId") String openId);

    List<UserRespVO> selectByDeptIds(Collection<Long> deptIds);

    /**
     * 根据部门ids查询出用户列表 过滤掉考勤组里有的
     *
     * @param deptIds
     * @param groupId
     * @return
     */
    List<UserRespVO> selectByDeptIdsFilterGroupUser(@Param("deptIds") Collection<Long> deptIds, @Param("groupId") Long groupId);

    List<Long> selectUserByBoss();

    /**
     * 获取考勤组里所有的用户
     *
     * @param mpPage
     * @param dto
     * @return
     */
    IPage<UserSimpleRespVO> getAllUserListByGroupIds(@Param("mpPage") IPage mpPage, @Param("dto") UserPageDTO dto);

    default IPage<LaborContractRespVO> selectContractPage(IPage<LaborContractRespVO> mpPage, LaborContractPageReqVO pageReqVO) {

        MPJLambdaWrapperX<AdminUserDO> queryWrapper = new MPJLambdaWrapperX<AdminUserDO>()
                .selectAs("a.id", LaborContractRespVO::getId)
                .selectAs(AdminUserDO::getId, LaborContractRespVO::getUserId)
                .selectAs(AdminUserDO::getNickname, LaborContractRespVO::getUserName)
                .selectAs(AdminUserDO::getDeptId, LaborContractRespVO::getDeptId)
                .selectAs(DeptDO::getName, LaborContractRespVO::getDeptName)
                .selectAs("a.signingDate", LaborContractRespVO::getSigningDate)
                .selectAs("a.expirationDate", LaborContractRespVO::getExpirationDate)
                .selectAs("a.contractDuration", LaborContractRespVO::getContractDuration)
                .selectAs("a.probationPeriodTime", LaborContractRespVO::getProbationPeriodTime)
                .selectAs("a.status", LaborContractRespVO::getStatus)
                .selectAs("a.createTime", LaborContractRespVO::getCreateTime)
                .selectCount("a.id", LaborContractRespVO::getSigningCount);
        queryWrapper.innerJoin(DeptDO.class, DeptDO::getId, AdminUserDO::getDeptId)
                .leftJoin("(SELECT\n" +
                        "           id,\n" +
                        "           user_id,\n" +
                        "           signing_date AS signingDate,\n" +
                        "           expiration_date AS expirationDate,\n" +
                        "           contract_duration AS contractDuration,\n" +
                        "           probation_period_time AS probationPeriodTime,\n" +
                        "           status,\n" +
                        "           create_time AS createTime\n" +
                        "         FROM\n" +
                        "           system_labor_contract lc\n" +
                        "           INNER JOIN (SELECT\n" +
                        "                           user_id AS userId,\n" +
                        "                           MAX(create_time) AS max_create_time\n" +
                        "                       FROM\n" +
                        "                           system_labor_contract\n" +
                        "                       WHERE\n" +
                        "                           deleted = 0\n" +
                        "                       GROUP BY user_id) max\n" +
                        "         WHERE\n" +
                        "           lc.user_id = max.userId\n" +
                        "           AND lc.create_time = max.max_create_time) a on a.user_id = t.id");
        queryWrapper.eq(AdminUserDO::getUserType, 1);
        queryWrapper.likeIfPresent(AdminUserDO::getNickname, pageReqVO.getUserName());
        queryWrapper.inIfPresent(AdminUserDO::getDeptId, pageReqVO.getDeptIds());
        if (Objects.nonNull(pageReqVO.getSigningDate())) {
            queryWrapper.between("a.signing_date", pageReqVO.getSigningDate()[0], pageReqVO.getSigningDate()[1]);
        }
        if (Objects.nonNull(pageReqVO.getExpirationDate())) {
            queryWrapper.between("a.expiration_date", pageReqVO.getExpirationDate()[0], pageReqVO.getExpirationDate()[1]);
        }
        queryWrapper.eq(Objects.nonNull(pageReqVO.getStatus()),"a.status", pageReqVO.getStatus());
        queryWrapper.groupBy(AdminUserDO::getId);
        queryWrapper.orderByAsc("a.status");
        queryWrapper.orderByAsc(AdminUserDO::getId);

        return selectJoinPage(mpPage, LaborContractRespVO.class, queryWrapper);
    }

    default PageResult<UserBirthdayRespVO> selectUserPageByBirthday(UserBirthdayPageReqVO pageReqVO,
                                                                    List<Long> deptIds,
                                                                    LocalDate date) {

        MPJLambdaWrapperX<AdminUserDO> queryWrapper = new MPJLambdaWrapperX<AdminUserDO>();
        queryWrapper.selectAs(AdminUserDO::getId, UserBirthdayRespVO::getUserId)
                .selectAs(AdminUserDO::getNickname, UserBirthdayRespVO::getNickname)
                .selectAs(AdminUserDO::getBirthdayDay, UserBirthdayRespVO::getBirthday)
                .leftJoin(AdminUserDO.class, AdminUserDO::getId, AdminUserDO::getId)
                .selectAs("d.name", UserBirthdayRespVO::getDeptName)
                .selectAs("p.name", UserBirthdayRespVO::getPostName)
                .selectAs("ps.name", UserBirthdayRespVO::getPositionName)
                .leftJoin("system_dept d on t.dept_id = d.id and d.deleted = 0")
                .leftJoin("system_post p on LOCATE(p.id, t.post_ids) and p.deleted = 0")
                .leftJoin("system_position ps on ps.id = t.position_id and ps.deleted = 0");

        queryWrapper.eq(AdminUserDO::getStatus, CommonStatusEnum.ENABLE.getStatus());
        queryWrapper.eq(AdminUserDO::getUserType, 1);
        queryWrapper.likeIfPresent(AdminUserDO::getNickname, pageReqVO.getName());
        queryWrapper.inIfPresent(AdminUserDO::getDeptId, deptIds);
        if ( (pageReqVO.getName() == null && pageReqVO.getDeptId() == null) || pageReqVO.getMonth() != null) {
            queryWrapper.eq("MONTH(t.birthday_day)",date.getMonthValue());
            queryWrapper.ge("DAY(t.birthday_day)", date.getDayOfMonth());
        }
        queryWrapper.groupBy("t.id");
        queryWrapper.orderByAsc("t.birthday_day");

        return selectJoinPage(pageReqVO, UserBirthdayRespVO.class, queryWrapper);
    }
}
