func createTaskHandler(c *gin.Context) {
	claims := jwt.ExtractClaims(c)
	var t models.Task
	err := c.BindJSON(&t)
	if err != nil {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusNotAcceptable)
		return
	}
	u, err := models.GetUser(claims["login"].(string))
	if err != nil {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusInternalServerError)
		return
	}
	task := models.Task{
		Content:        t.Content,
		DueDate:        t.DueDate.Local(),
		Subject:        t.Subject,
		Title:          t.Title,
		Visibility:     t.Visibility,
		CreatedByLogin: u.Login,
		UpdatedByLogin: u.Login,
	}
	task.CreatedByLogin = u.Login
	task.UpdatedByLogin = u.Login
	if !u.Teacher {
		if t.Visibility == models.ClassVisibility {
			task.Region = u.Region
			task.Promotion = u.Promotion
			task.Class = u.Class
			task.Semester = u.Semester
		}
		if t.Visibility == models.PromotionVisibility {
			task.Promotion = u.Promotion
			task.Semester = u.Semester
		}
	} else {
		if t.Visibility == models.ClassVisibility {
			task.Region = t.Region
			task.Promotion = t.Promotion
			task.Class = t.Class
			task.Semester = t.Semester
		}
		if t.Visibility == models.PromotionVisibility {
			task.Promotion = t.Promotion
			task.Semester = t.Semester
		}
	}
	if t.Visibility == models.StudentsVisibility {
		task.Members = t.Members
	}
	err = task.Validate()
	if err != nil {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusNotAcceptable)
		return
	}
	err = task.Insert()
	if err != nil {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusInternalServerError)
		return
	}
	zap.S().Info("User ", u.Name, " created task ", task.ShortID)
	c.JSON(http.StatusOK, task.ShortID)
}
@Summary Create task
@Tags tasks
@Description Create a new task
@Accept  json
@Param   task body    models.Task     true        "Task"
@Success 200	"OK"
@Failure 401	"Unauthorized"
@Failure 404	"Not found"
@Failure 406	"Not acceptable"
@Failure 500 "Server error"
@Router /tasks [POST]
package api
import (
	"net/http"
	jwt "github.com/appleboy/gin-jwt/v2"
	"github.com/aureleoules/epitaf/models"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)
func handleTasks() {
	router.POST("/tasks", createTaskHandler)
	router.GET("/tasks/:id", getTaskHandler)
	router.GET("/tasks", getTasksHandler)
	router.PUT("/tasks/:id", editTaskHandler)
	router.DELETE("/tasks/:id", deleteTaskHandler)
	router.POST("/tasks/:id/complete", completeTaskHandler)
	router.DELETE("/tasks/:id/complete", unCompleteTaskHandler)
}
func completeTaskHandler(c *gin.Context) {
	claims := jwt.ExtractClaims(c)
	u, err := models.GetUser(claims["login"].(string))
	if err != nil {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusInternalServerError)
		return
	}
	task, err := models.GetUserTask(c.Param("id"), u.Login)
	if err != nil {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusNotFound)
		return
	}
	if task.Completed {
		c.AbortWithStatus(http.StatusNotAcceptable)
		return
	}
	if !u.CanViewTask(*task) {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusUnauthorized)
		return
	}
	err = task.Mark(u.Login)
	if err != nil {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusInternalServerError)
		return
	}
	c.Status(http.StatusOK)
}
func unCompleteTaskHandler(c *gin.Context) {
	claims := jwt.ExtractClaims(c)
	u, err := models.GetUser(claims["login"].(string))
	if err != nil {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusInternalServerError)
		return
	}
	task, err := models.GetUserTask(c.Param("id"), u.Login)
	if err != nil {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusNotFound)
		return
	}
	if !task.Completed {
		c.AbortWithStatus(http.StatusNotAcceptable)
		return
	}
	if !u.CanViewTask(*task) {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusUnauthorized)
		return
	}
	err = task.Unmark(u.Login)
	if err != nil {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusInternalServerError)
		return
	}
	c.Status(http.StatusOK)
}
func editTaskHandler(c *gin.Context) {
	claims := jwt.ExtractClaims(c)
	u, err := models.GetUser(claims["login"].(string))
	if err != nil {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusInternalServerError)
		return
	}
	task, err := models.GetUserTask(c.Param("id"), u.Login)
	if err != nil {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusNotFound)
		return
	}
	var t models.Task
	err = c.BindJSON(&t)
	if err != nil {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusNotAcceptable)
		return
	}
	if task.CreatedByLogin != u.Login && t.Visibility != "" && task.Visibility != t.Visibility {
		c.AbortWithStatus(http.StatusUnauthorized)
		return
	}
	if !u.CanEditTask(*task) {
		c.AbortWithStatus(http.StatusUnauthorized)
		return
	}
	update := t.PrepareUpdate(*task, *u)
	update.UpdatedByLogin = u.Login
	update.ShortID = task.ShortID
	err = update.Validate()
	if err != nil {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusNotAcceptable)
		return
	}
	err = models.UpdateTask(update)
	if err != nil {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusInternalServerError)
		return
	}
	zap.S().Info("User ", u.Name, " updated task ", update.ShortID)
	c.Status(http.StatusOK)
}
func deleteTaskHandler(c *gin.Context) {
	claims := jwt.ExtractClaims(c)
	u, err := models.GetUser(claims["login"].(string))
	if err != nil {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusInternalServerError)
		return
	}
	task, err := models.GetUserTask(c.Param("id"), u.Login)
	if err != nil {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusNotFound)
		return
	}
	if !u.CanDeleteTask(*task) {
		c.AbortWithStatus(http.StatusUnauthorized)
		return
	}
	err = models.DeleteTask(task.ShortID)
	if err != nil {
		c.AbortWithStatus(http.StatusInternalServerError)
		return
	}
	zap.S().Info("User ", u.Name, " deleted task ", task.ShortID)
	c.Status(http.StatusOK)
}
func getTaskHandler(c *gin.Context) {
	claims := jwt.ExtractClaims(c)
	u, err := models.GetUser(claims["login"].(string))
	if err != nil {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusInternalServerError)
		return
	}
	task, err := models.GetUserTask(c.Param("id"), u.Login)
	if err != nil {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusNotFound)
		return
	}
	if !u.CanViewTask(*task) {
		c.AbortWithStatus(http.StatusUnauthorized)
		return
	}
	c.JSON(http.StatusOK, task)
}
func getTasksHandler(c *gin.Context) {
	claims := jwt.ExtractClaims(c)
	u, err := models.GetUser(claims["login"].(string))
	if err != nil {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusInternalServerError)
		return
	}
	var tasks []models.Task
	var query models.Filters
	err = c.BindQuery(&query)
	if err != nil {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusNotAcceptable)
		return
	}
	err = query.Validate()
	if err != nil {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusNotAcceptable)
		return
	}
	if u.Teacher {
		tasks, err = models.GetTeacherTasksRange(query.StartDate, query.EndDate)
	} else {
		tasks, err = models.GetTasksRange(*u, query)
	}
	if err != nil {
		zap.S().Error(err)
		c.AbortWithStatus(http.StatusInternalServerError)
		return
	}
	zap.S().Info(u.Name + " fetched tasks.")
	c.JSON(http.StatusOK, tasks)
}