package workspace

import (
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"

	wsapi "github.com/tidbcloud/aisupport/packages/sdk-go/contracts/api/ticket-manager/workspace"
	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"
	workspacesvcapi "github.com/tidbcloud/aisupport/services/ticket-manager/internal/services/workspace/api"
)

// ListTasks lists workspace tasks.
//
//	@Summary	List workspace tasks
//	@Id			WorkspaceHandlerListTasks
//	@Tags		WorkspaceHandler
//	@Accept		json
//	@Produce	json
//	@Param		id		path		int						true	"Workspace ID"
//	@Param		param	query		wsapi.ListTasksRequest	false	"param"
//	@Success	200		{object}	wsapi.ListTasksResponse
//	@Failure	default	{object}	base.BaseResponse
//	@Router		/api/v1/ticketmanager/workspace/workspaces/{id}/tasks [get]
func (h *Handler) ListTasks(c *gin.Context) {
	workspaceID, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		apiutils.Fail(c, errs.APIErrorNew(http.StatusBadRequest, err))
		return
	}

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

	param := workspacesvcapi.ListTasksParam{
		PriorityIn: req.Priority,
		Page: &workspacesvcapi.PageParam{
			Page:     int(req.Page),
			PageSize: int(req.PageSize),
		},
	}
	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.Workspace.ListTasks(c, workspaceID, param)
	if err != nil {
		apiutils.Fail(c, err)
		return
	}

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

// CreateTask creates a workspace task.
//
//	@Summary	Create a workspace task
//	@Id			WorkspaceHandlerCreateTask
//	@Tags		WorkspaceHandler
//	@Accept		json
//	@Produce	json
//	@Param		id		path		int						true	"Workspace ID"
//	@Param		request	body		wsapi.CreateTaskRequest	true	"Workspace task create payload"
//	@Success	200		{object}	wsapi.CreateTaskResponse
//	@Failure	default	{object}	base.BaseResponse
//	@Router		/api/v1/ticketmanager/workspace/workspaces/{id}/tasks [post]
func (h *Handler) CreateTask(c *gin.Context) {
	workspaceID, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		apiutils.Fail(c, errs.APIErrorNew(http.StatusBadRequest, err))
		return
	}

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

	task, err := h.Workspace.CreateTask(c, workspaceID, workspacesvcapi.CreateTaskParam{
		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, &wsapi.CreateTaskResponse{
		Task: task,
	})
}

// GetTask gets a workspace task.
//
//	@Summary	Get a workspace task
//	@Id			WorkspaceHandlerGetTask
//	@Tags		WorkspaceHandler
//	@Accept		json
//	@Produce	json
//	@Param		id		path		int	true	"Workspace ID"
//	@Param		task_id	path		int	true	"Task ID"
//	@Success	200		{object}	wsapi.GetTaskResponse
//	@Failure	default	{object}	base.BaseResponse
//	@Router		/api/v1/ticketmanager/workspace/workspaces/{id}/tasks/{task_id} [get]
func (h *Handler) GetTask(c *gin.Context) {
	workspaceID, taskID, ok := h.parseWorkspaceTaskIDs(c)
	if !ok {
		return
	}

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

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

// UpdateTask updates a workspace task.
//
//	@Summary	Update a workspace task
//	@Id			WorkspaceHandlerUpdateTask
//	@Tags		WorkspaceHandler
//	@Accept		json
//	@Produce	json
//	@Param		id		path		int						true	"Workspace ID"
//	@Param		task_id	path		int						true	"Task ID"
//	@Param		request	body		wsapi.UpdateTaskRequest	true	"Workspace task update payload"
//	@Success	200		{object}	wsapi.UpdateTaskResponse
//	@Failure	default	{object}	base.BaseResponse
//	@Router		/api/v1/ticketmanager/workspace/workspaces/{id}/tasks/{task_id} [put]
func (h *Handler) UpdateTask(c *gin.Context) {
	workspaceID, taskID, ok := h.parseWorkspaceTaskIDs(c)
	if !ok {
		return
	}

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

	updated, err := h.Workspace.UpdateTask(c, workspaceID, taskID, workspacesvcapi.UpdateTaskParam{
		UpdateTaskParam: 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, &wsapi.UpdateTaskResponse{
		Task: updated,
	})
}

// CompleteTask completes a workspace task.
//
//	@Summary	Complete a workspace task
//	@Id			WorkspaceHandlerCompleteTask
//	@Tags		WorkspaceHandler
//	@Accept		json
//	@Produce	json
//	@Param		id		path		int	true	"Workspace ID"
//	@Param		task_id	path		int	true	"Task ID"
//	@Success	200		{object}	wsapi.CompleteTaskResponse
//	@Failure	default	{object}	base.BaseResponse
//	@Router		/api/v1/ticketmanager/workspace/workspaces/{id}/tasks/{task_id}/complete [post]
func (h *Handler) CompleteTask(c *gin.Context) {
	workspaceID, taskID, ok := h.parseWorkspaceTaskIDs(c)
	if !ok {
		return
	}

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

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

// DeleteTask deletes a workspace task.
//
//	@Summary	Delete a workspace task
//	@Id			WorkspaceHandlerDeleteTask
//	@Tags		WorkspaceHandler
//	@Accept		json
//	@Produce	json
//	@Param		id		path		int	true	"Workspace ID"
//	@Param		task_id	path		int	true	"Task ID"
//	@Success	200		{object}	map[string]interface{}
//	@Failure	default	{object}	base.BaseResponse
//	@Router		/api/v1/ticketmanager/workspace/workspaces/{id}/tasks/{task_id} [delete]
func (h *Handler) DeleteTask(c *gin.Context) {
	workspaceID, taskID, ok := h.parseWorkspaceTaskIDs(c)
	if !ok {
		return
	}

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

	apiutils.Success(c, nil)
}

func (h *Handler) parseWorkspaceTaskIDs(c *gin.Context) (uint64, uint64, bool) {
	workspaceID, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		apiutils.Fail(c, errs.APIErrorNew(http.StatusBadRequest, err))
		return 0, 0, false
	}
	taskID, err := strconv.ParseUint(c.Param("task_id"), 10, 64)
	if err != nil {
		apiutils.Fail(c, errs.APIErrorNew(http.StatusBadRequest, err))
		return 0, 0, false
	}
	return workspaceID, taskID, true
}
