package task

import (
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"

	taskapi "github.com/tidbcloud/aisupport/packages/sdk-go/contracts/api/ticket-manager/task"
	apiutils "github.com/tidbcloud/aisupport/packages/sdk-go/infra/apiserver/utils"
	"github.com/tidbcloud/aisupport/packages/sdk-go/infra/errs"
	tasksvcapi "github.com/tidbcloud/aisupport/services/ticket-manager/internal/services/task/api"
)

// ListTasks lists tasks.
//
//	@Summary	List tasks
//	@Id			TaskHandlerListTasks
//	@Tags		TaskHandler
//	@Accept		json
//	@Produce	json
//	@Param		param	query		taskapi.ListTasksRequest	false	"param"
//	@Success	200		{object}	taskapi.ListTasksResponse
//	@Failure	default	{object}	base.BaseResponse
//	@Router		/api/v1/ticketmanager/task/tasks [get]
func (h *Handler) ListTasks(c *gin.Context) {
	var req taskapi.ListTasksRequest
	if err := c.ShouldBindQuery(&req); err != nil {
		apiutils.Fail(c, errs.APIErrorNew(http.StatusBadRequest, err))
		return
	}

	param := tasksvcapi.ListTasksParam{
		PriorityIn: req.Priority,
		Page: &tasksvcapi.PageParam{
			Page:     int(req.Page),
			PageSize: int(req.PageSize),
		},
	}
	if req.TaskListID != 0 {
		param.TaskListIDIs = &req.TaskListID
	}
	if req.ParentTaskID != 0 {
		param.ParentTaskIDIs = &req.ParentTaskID
	}
	if req.Creator != "" {
		param.CreatorIs = &req.Creator
	}
	if req.Group != "" {
		param.GroupIs = &req.Group
	}

	tasks, total, err := h.Task.ListTasks(c, param)
	if err != nil {
		apiutils.Fail(c, err)
		return
	}

	apiutils.Success(c, &taskapi.ListTasksResponse{
		Tasks: tasks,
		Total: total,
	})
}

// CreateTask creates a task.
//
//	@Summary	Create a task
//	@Id			TaskHandlerCreateTask
//	@Tags		TaskHandler
//	@Accept		json
//	@Produce	json
//	@Param		request	body		taskapi.CreateTaskRequest	true	"Task create payload"
//	@Success	200		{object}	taskapi.CreateTaskResponse
//	@Failure	default	{object}	base.BaseResponse
//	@Router		/api/v1/ticketmanager/task/tasks [post]
func (h *Handler) CreateTask(c *gin.Context) {
	var req taskapi.CreateTaskRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		apiutils.Fail(c, errs.APIErrorf(http.StatusBadRequest, "invalid tasks query"))
		return
	}

	task, err := h.Task.CreateTask(c, tasksvcapi.CreateTaskParam{
		Title:        req.Title,
		Description:  req.Description,
		Priority:     req.Priority,
		DueAt:        req.DueAt,
		Creator:      req.Creator,
		StartedAt:    req.StartedAt,
		ParentTaskID: req.ParentTaskID,
		TaskListID:   req.TaskListID,
		Group:        req.Group,
		Members:      req.Members,
	})
	if err != nil {
		apiutils.Fail(c, err)
		return
	}

	apiutils.Success(c, &taskapi.CreateTaskResponse{
		Task: task,
	})
}

// GetTask gets a task.
//
//	@Summary	Get a task
//	@Id			TaskHandlerGetTask
//	@Tags		TaskHandler
//	@Accept		json
//	@Produce	json
//	@Param		id		path		int	true	"Task ID"
//	@Success	200		{object}	taskapi.GetTaskResponse
//	@Failure	default	{object}	base.BaseResponse
//	@Router		/api/v1/ticketmanager/task/tasks/{id} [get]
func (h *Handler) GetTask(c *gin.Context) {
	taskID, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		apiutils.Fail(c, errs.APIErrorNew(http.StatusBadRequest, err))
		return
	}

	task, err := h.Task.GetTask(c, taskID)
	if err != nil {
		apiutils.Fail(c, err)
		return
	}

	apiutils.Success(c, &taskapi.GetTaskResponse{
		Task: task,
	})
}

// UpdateTask updates a task.
//
//	@Summary	Update a task
//	@Id			TaskHandlerUpdateTask
//	@Tags		TaskHandler
//	@Accept		json
//	@Produce	json
//	@Param		id		path		int							true	"Task ID"
//	@Param		request	body		taskapi.UpdateTaskRequest	true	"Task update payload"
//	@Success	200		{object}	taskapi.UpdateTaskResponse
//	@Failure	default	{object}	base.BaseResponse
//	@Router		/api/v1/ticketmanager/task/tasks/{id} [put]
func (h *Handler) UpdateTask(c *gin.Context) {
	taskID, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		apiutils.Fail(c, errs.APIErrorNew(http.StatusBadRequest, err))
		return
	}

	var req taskapi.UpdateTaskRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		apiutils.Fail(c, errs.APIErrorNew(http.StatusBadRequest, err))
		return
	}

	updated, err := h.Task.UpdateTask(c, taskID, tasksvcapi.UpdateTaskParam{
		Title:        req.Title,
		Description:  req.Description,
		Priority:     req.Priority,
		DueAt:        req.DueAt,
		Creator:      req.Creator,
		StartedAt:    req.StartedAt,
		ParentTaskID: req.ParentTaskID,
		Group:        req.Group,
		Members:      req.Members,
	})
	if err != nil {
		apiutils.Fail(c, err)
		return
	}

	apiutils.Success(c, &taskapi.UpdateTaskResponse{
		Task: updated,
	})
}

// DeleteTask deletes a task.
//
//	@Summary	Delete a task
//	@Id			TaskHandlerDeleteTask
//	@Tags		TaskHandler
//	@Accept		json
//	@Produce	json
//	@Param		id		path		int	true	"Task ID"
//	@Success	200		{object}	map[string]interface{}
//	@Failure	default	{object}	base.BaseResponse
//	@Router		/api/v1/ticketmanager/task/tasks/{id} [delete]
func (h *Handler) DeleteTask(c *gin.Context) {
	taskID, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		apiutils.Fail(c, errs.APIErrorNew(http.StatusBadRequest, err))
		return
	}

	if err := h.Task.DeleteTask(c, taskID); err != nil {
		apiutils.Fail(c, err)
		return
	}

	apiutils.Success(c, nil)
}

// CompleteTask completes a task.
//
//	@Summary	Complete a task
//	@Id			TaskHandlerCompleteTask
//	@Tags		TaskHandler
//	@Accept		json
//	@Produce	json
//	@Param		id		path		int	true	"Task ID"
//	@Success	200		{object}	taskapi.CompleteTaskResponse
//	@Failure	default	{object}	base.BaseResponse
//	@Router		/api/v1/ticketmanager/task/tasks/{id}/complete [post]
func (h *Handler) CompleteTask(c *gin.Context) {
	taskID, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		apiutils.Fail(c, errs.APIErrorNew(http.StatusBadRequest, err))
		return
	}

	updated, err := h.Task.CompleteTask(c, taskID)
	if err != nil {
		apiutils.Fail(c, err)
		return
	}

	apiutils.Success(c, &taskapi.CompleteTaskResponse{
		Task: updated,
	})
}
