package cn.edu.whu.boot.allocation.mapper;

import cn.edu.whu.boot.allocation.controllers.dtos.Worker;
import cn.edu.whu.boot.allocation.entities.TaskUserCell;
import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface TaskUserCellMapper {
    @Select("SELECT id, task_id, user_id, cell_geohash " +
            "FROM task_user_cell " +
            "WHERE id = #{id}")
    @Results(
            {
                    @Result(property = "taskId", column = "task_id"),
                    @Result(property = "userId", column = "user_id"),
                    @Result(property = "cellGeohash", column = "cell_geohash")
            }
    )
    TaskUserCell findById(@Param("id") int id);

    @Select("SELECT id, task_id, user_id, cell_geohash " +
            "FROM task_user_cell " +
            "WHERE task_id = #{taskId} AND user_id = #{userId}")
    @Results(
            {
                    @Result(property = "taskId", column = "task_id"),
                    @Result(property = "userId", column = "user_id"),
                    @Result(property = "cellGeohash", column = "cell_geohash")
            }
    )
    List<TaskUserCell> findByTaskIdAndUserId(@Param("taskId") int taskId, @Param("userId") int userId);

    @Select("SELECT tmp.id AS user_id, tmp.real_name, tmp.work_role, tuc.cell_geohash\n" +
            "FROM task_user_cell tuc\n" +
            "         INNER JOIN (SELECT tur.work_role, us.id, us.real_name\n" +
            "                     FROM task_user_role tur\n" +
            "                              INNER JOIN user_staff us ON tur.user_id = us.id\n" +
            "                     WHERE tur.task_id = #{taskId}) tmp ON tuc.user_id = tmp.id\n" +
            "WHERE tuc.task_id = #{taskId}")
    @Results(
            {
                    @Result(property = "id", column = "user_id"),
                    @Result(property = "username", column = "real_name"),
                    @Result(property = "geohash", column = "cell_geohash"),
                    @Result(property = "role", column = "work_role")
            }
    )
    List<Worker> findCellAndUserByTaskId(@Param("taskId") int taskId);

    @Select("SELECT a.user_id, a.cell_geohash, b.username, c.geojson, d.work_role " +
            "FROM task_user_cell AS a, user_staff AS b, task_cell AS c, task_user_role as d " +
            "WHERE a.task_id = #{taskId} AND a.user_id = #{userId} " +
            "AND a.user_id = b.id AND a.task_id = c.task_id AND a.cell_geohash = c.geohash " +
            "AND d.task_id = a.task_id AND d.user_id = a.user_id")
    @Results(
            {
                    @Result(property = "id", column = "user_id"),
                    @Result(property = "username", column = "username"),
                    @Result(property = "geohash", column = "cell_geohash"),
                    @Result(property = "geojson", column = "geojson"),
                    @Result(property = "role", column = "work_role")
            }
    )
    List<Worker> findCellAndUserByTaskIdAndUserId(@Param("taskId") int taskId, @Param("userId") int userId);

    @Select("SELECT id, task_id, user_id, cell_geohash " +
            "FROM task_user_cell " +
            "WHERE task_id = #{taskId} AND user_id = #{userId} AND cell_geohash = #{geohash}")
    @Results(
            {
                    @Result(property = "taskId", column = "task_id"),
                    @Result(property = "userId", column = "user_id"),
                    @Result(property = "cellGeohash", column = "cell_geohash")
            }
    )
    TaskUserCell findByTaskIdAndUserIdAndCellGeohash(@Param("taskId") int taskId, @Param("userId") int userId, @Param("geohash") String geohash);

    @Select("SELECT count(id) FROM task_user_cell WHERE task_id = #{taskId} AND user_id = #{userId}")
    int countByTaskIdAndUserId(@Param("taskId") int taskId, @Param("userId") int userId);

    @Select("INSERT INTO task_user_cell(task_id, user_id, cell_geohash)" +
            " VALUES(#{taskId}, #{userId}, #{cellGeohash}) " +
            "RETURNING id")
    int insert(TaskUserCell taskUserCell);

    @Insert({
            "<script>",
            "INSERT INTO task_user_cell(task_id, user_id, cell_geohash)",
            "VALUES" +
                    "<foreach item='item' index='item' collection='list' open='' separator=',' close=''>" +
                    "(" +
                    "#{item.taskId}, #{item.userId}, #{item.cellGeohash}",
            ")" +
                    "</foreach>",
            "</script>"})
    void insertForeach(@Param("list") List<TaskUserCell> list);

    @Select("WITH rows AS (" +
            "UPDATE task_user_cell " +
            "SET user_id = #{userId}" +
            " WHERE task_id = #{taskId} AND cell_geohash = #{cellGeohash} " +
            "RETURNING 1" +
            ") SELECT count(*) FROM rows")
    int updateUserIdByTaskIdAndCellGeohash(@Param("taskId") int taskId, @Param("cellGeohash") String cellGeohash, @Param("userId") int userId);

    @Delete("DELETE FROM task_user_cell WHERE task_id = #{taskId}")
    void deleteByTaskId(@Param("taskId") int taskId);

    @Delete("DELETE FROM task_user_cell WHERE task_id = #{taskId} AND user_id = #{userId}")
    void deleteByTaskIdAndUserId(@Param("taskId") int taskId, @Param("userId") int userId);

    @Delete("DELETE FROM task_user_cell WHERE task_id = #{taskId} AND cell_geohash = #{geohash} AND user_id = #{userId}")
    void deleteByTaskIdAndCellGeohashAndUserId(@Param("taskId") int taskId,@Param("geohash") String geohash, @Param("userId") int userId);

    @Delete("DELETE FROM task_user_cell WHERE task_id = #{taskId} AND cell_geohash = #{geohash}")
    void deleteByTaskIdAndCellGeohash(@Param("taskId") int taskId, @Param("geohash") String geohash);
}