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

import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
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.worklog.vo.loginstance.LogInstancePageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.worklog.vo.loginstance.LogInstanceRespVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.UserPostDO;
import cn.iocoder.yudao.module.system.dal.dataobject.worklog.LogInstanceDO;
import cn.iocoder.yudao.module.system.service.worklog.dto.LogReadUserRespDTO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

/**
 * 日志实例的拓展 Mapper
 *
 * @author 符溶馨
 */
@Mapper
public interface LogInstanceMapper extends BaseMapperX<LogInstanceDO> {


    default PageResult<LogInstanceDO> getUpLog(Long userId, Long formId) {

        return selectPage(new PageParam().setPageNo(1).setPageSize(1), new LambdaQueryWrapperX<LogInstanceDO>()
                .eq(LogInstanceDO::getStartUserId, userId)
                .eqIfPresent(LogInstanceDO::getFormId, formId)
                .orderByDesc(LogInstanceDO::getCreateTime));
    }

    default Long getLogByFormId(Long formId, Long userId, List<String> dateList) {

        return selectCount(new LambdaQueryWrapperX<LogInstanceDO>()
                .eq(LogInstanceDO::getFormId, formId)
                .eq(LogInstanceDO::getStartUserId, userId)
                .in(LogInstanceDO::getTime, dateList));
    }

    default IPage<LogInstanceRespVO> selectPageResult(@Param("page") IPage<LogInstanceRespVO> page,
                                                      @Param("reqVO") LogInstancePageReqVO reqVO,
                                                      @Param("userId") Long userId,
                                                      @Param("userIds") List<Long> userIds) {


        MPJLambdaWrapperX<LogInstanceDO> queryWrapper = new MPJLambdaWrapperX<>();
        queryWrapper.selectAll(LogInstanceDO.class);
        queryWrapper.selectAs("e.read_status", LogInstanceRespVO::getReadStatus);
        queryWrapper.selectAs("COALESCE(c.readCount, 0)", LogInstanceRespVO::getReadCount);
        queryWrapper.selectAs("COALESCE(d.unreadCount, 0)", LogInstanceRespVO::getUnreadCount);
        queryWrapper.selectAs("COALESCE(b.comment, 0)", LogInstanceRespVO::getComment);
        queryWrapper.innerJoin(UserPostDO.class, "userPost", UserPostDO::getUserId, LogInstanceDO::getStartUserId);
        queryWrapper.innerJoin(DeptDO.class, "dept", DeptDO::getId, LogInstanceDO::getDeptId);
        queryWrapper.innerJoin(PostDO.class, "post", PostDO::getId, UserPostDO::getPostId);
//        queryWrapper.leftJoin(LogReadDo.class, "e", on -> on
//                .eq(LogReadDo::getLogInstanceId, LogInstanceDO::getId)
//                .eq(LogReadDo::getReadUserId, userId)
//                .eq(LogReadDo::getDeleted, 0));
        queryWrapper.leftJoin("work_log_read e on e.log_instance_id = t.id and e.deleted = 0 and e.read_user_id = " + userId);
        queryWrapper.leftJoin("(SELECT log_instance_id, COUNT(log_instance_id) AS readCount FROM work_log_read where read_status = 1 and deleted = 0 GROUP BY log_instance_id) c on t.id = c.log_instance_id");
        queryWrapper.leftJoin("(SELECT log_instance_id, COUNT(log_instance_id) AS unReadCount FROM work_log_read where read_status = 0 and deleted = 0 GROUP BY log_instance_id) AS d ON t.id = d.log_instance_id");
        queryWrapper.leftJoin("(SELECT work_log_id, COUNT(work_log_id) AS comment FROM work_log_comment GROUP BY work_log_id) AS b ON t.id = b.work_log_id");
        queryWrapper.eqIfPresent(LogInstanceDO::getDeptId, reqVO.getDeptId());
        queryWrapper.eqIfPresent(LogInstanceDO::getFormId, reqVO.getFormId());
        queryWrapper.eqIfPresent(LogInstanceDO::getStartUserId, reqVO.getStartUserId());
        queryWrapper.betweenIfPresent(LogInstanceDO::getTime, reqVO.getCreateTime());
        queryWrapper.inIfPresent(LogInstanceDO::getStartUserId, userIds);
        queryWrapper.ne(LogInstanceDO::getStartUserId, userId);

        if (reqVO.getReadStatus() != null) {
            queryWrapper.eq("e.read_status", reqVO.getReadStatus());
        }
        if (reqVO.getIsProduce() != null && reqVO.getIsProduce() == 1) {
            queryWrapper.like(DeptDO::getFlag, "166");
        }
        if (reqVO.getIsProduce() != null && reqVO.getIsProduce() == 2) {
            queryWrapper.notLike(DeptDO::getFlag, "166");
        }
        queryWrapper.groupBy(LogInstanceDO::getId);
        queryWrapper.orderByDesc(LogInstanceDO::getTime);
        queryWrapper.orderByAsc(PostDO::getSort);
        queryWrapper.orderByDesc(LogInstanceDO::getCreateTime);

        return selectJoinPage(page, LogInstanceRespVO.class, queryWrapper);
    }

    IPage<LogInstanceRespVO> selectMyPageResult(@Param("page") IPage<LogInstanceRespVO> page,
                                                @Param("reqVO") LogInstancePageReqVO reqVO,
                                                @Param("userId") Long userId);

    @DataPermission(enable = false)
    List<LogReadUserRespDTO> selectRaedUser(@Param("userId")Long userId, @Param("deptId")Long deptId);

    /**
     * 获取上一篇下一篇
     *
     * @param dto
     * @param id
     * @param userId
     * @param type
     * @return
     */
    LogInstanceRespVO getMyNextOrUp(@Param("reqVO") LogInstancePageReqVO dto,
                                  @Param("id") Long id, @Param("userId") Long userId,
                                  @Param("type") Integer type,
                                  @Param("userIds") List<Long> userIds);

    default IPage<LogInstanceRespVO> getNextOrUp(@Param("reqVO") LogInstancePageReqVO reqVO,
                                                 @Param("id") Long id,
                                                 @Param("userId") Long userId,
                                                 @Param("type") Integer type,
                                                 @Param("userIds") List<Long> userIds){

        String sql = "";

        MPJLambdaWrapperX<LogInstanceDO> queryWrapper = new MPJLambdaWrapperX<>();
        queryWrapper.selectAs(LogInstanceDO::getId, LogInstanceRespVO::getId);
        queryWrapper.selectAs(LogInstanceDO::getName, LogInstanceRespVO::getName);
        queryWrapper.innerJoin(UserPostDO.class, "userPost", UserPostDO::getUserId, LogInstanceDO::getStartUserId);
        queryWrapper.innerJoin(DeptDO.class, "dept", DeptDO::getId, LogInstanceDO::getDeptId);
        queryWrapper.innerJoin(PostDO.class, "post", PostDO::getId, UserPostDO::getPostId);
        if (type == 1) {
            sql =   "   (t.time > tt.time) or\n" +
                    "   (t.time = tt.time and tt.sort > post.sort) or\n" +
                    "   (t.time = tt.time and tt.sort = post.sort and tt.create_time < t.create_time)";

            queryWrapper.orderByAsc(LogInstanceDO::getTime);
            queryWrapper.orderByDesc(PostDO::getSort);
            queryWrapper.orderByAsc(LogInstanceDO::getCreateTime);
        }
        if (type == 0) {
            sql =   "   (t.time < tt.time) or\n" +
                    "   (t.time = tt.time and tt.sort < post.sort) or\n" +
                    "   (t.time = tt.time and tt.sort = post.sort and tt.create_time > t.create_time)";

            queryWrapper.orderByDesc(LogInstanceDO::getTime);
            queryWrapper.orderByAsc(PostDO::getSort);
            queryWrapper.orderByDesc(LogInstanceDO::getCreateTime);
        }
        queryWrapper.innerJoin("(\n" +
                "SELECT \n" +
                "   a.id,\n" +
                "   a.name,\n" +
                "   a.time,\n" +
                "   d.sort,\n" +
                "   a.create_time\n" +
                "FROM \n" +
                "   work_log_instance_ext a\n" +
                "   INNER JOIN system_user_post b ON (b.user_id = a.start_user_id) \n" +
                "   INNER JOIN system_dept c ON (c.id = a.dept_id) \n" +
                "   INNER JOIN system_post d ON (d.id = b.post_id) \n" +
                "WHERE \n" +
                "   a.id = " + id + "\n" +
                "   AND a.deleted = 0 \n" +
                "   AND b.deleted = 0 \n" +
                "   AND c.deleted = 0 \n" +
                "   AND d.deleted = 0\n" +
                ") tt on \n" + sql);
        queryWrapper.eqIfPresent(LogInstanceDO::getDeptId, reqVO.getDeptId());
        queryWrapper.eqIfPresent(LogInstanceDO::getFormId, reqVO.getFormId());
        queryWrapper.eqIfPresent(LogInstanceDO::getStartUserId, reqVO.getStartUserId());
        queryWrapper.betweenIfPresent(LogInstanceDO::getTime, reqVO.getCreateTime());
        queryWrapper.inIfPresent(LogInstanceDO::getStartUserId, userIds);
        queryWrapper.ne(LogInstanceDO::getStartUserId, userId);

        if (reqVO.getIsProduce() != null && reqVO.getIsProduce() == 1) {
            queryWrapper.like(DeptDO::getFlag, "166");
        }
        if (reqVO.getIsProduce() != null && reqVO.getIsProduce() == 2) {
            queryWrapper.notLike(DeptDO::getFlag, "166");
        }

        return selectJoinPage(new Page<>(1, 1), LogInstanceRespVO.class, queryWrapper);
    }
}