package task

import (
	"net/http"
	"strconv"
	"strings"

	"github.com/tidbcloud/AgentTeam/internal/api"
	"github.com/tidbcloud/AgentTeam/internal/api/dto"
	"github.com/tidbcloud/AgentTeam/internal/api/dto/converter"
)

// ResourceList handles the canonical channel Task collection endpoint with
// bounded browse and text search in one GET resource using query parameters.
func (handler *CollectionHandler) ResourceList(r api.WorkspaceScopedRequest) (api.Response, error) {
	channelID := strings.TrimSpace(r.Gin.Param("channelId"))
	if channelID == "" {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "channelId is required")
	}

	limit := 20
	if raw := strings.TrimSpace(r.Gin.Query("limit")); raw != "" {
		parsed, err := strconv.Atoi(raw)
		if err != nil || parsed <= 0 || parsed > 100 {
			return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "limit must be between 1 and 100")
		}
		limit = parsed
	}
	includeSubtasks := false
	if raw := strings.TrimSpace(r.Gin.Query("include_subtasks")); raw != "" {
		parsed, err := strconv.ParseBool(raw)
		if err != nil {
			return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "include_subtasks must be a boolean")
		}
		includeSubtasks = parsed
	}
	quickFilters := append([]string(nil), r.Gin.QueryArray("quick_filters")...)
	status, err := canonicalTaskBrowseStatusFilter(r.Gin.Query("status"))
	if err != nil {
		return api.Response{}, err
	}
	dtoQuery := dto.TaskBrowseRequest{
		Limit: limit, SearchQuery: strings.TrimSpace(r.Gin.Query("query")),
		SortMode: strings.TrimSpace(r.Gin.Query("sort")), QuickFilters: quickFilters,
		IncludeSubtasks: includeSubtasks, Cursor: strings.TrimSpace(r.Gin.Query("cursor")),
	}
	converted, err := converter.FromTaskBrowseQuery(dtoQuery)
	if err != nil {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, err.Error())
	}
	converted.StatusFilter = status
	response, err := handler.taskBoard.BrowseChannelTasks(r.Context(), BrowseChannelTasksRequest{
		Context: NewUserServiceContext(r.WorkspaceID(), r.User.User.ID, r.User.User.Name),
		Board:   BoardRef{ChannelID: channelID}, Query: taskBrowseQueryForPort(converted),
	})
	if err != nil {
		return api.Response{}, err
	}
	return api.OK(converter.ToTaskBrowseResponse(taskboardTaskRowBrowsePageForDTO(response))), nil
}

func canonicalTaskBrowseStatusFilter(value string) (string, error) {
	switch status := strings.TrimSpace(value); status {
	case "", "all":
		return "", nil
	case "active", "todo", "in_progress", "in_review", "done":
		return status, nil
	default:
		return "", api.NewHTTPError(
			http.StatusBadRequest,
			"status must be one of active, all, todo, in_progress, in_review, or done",
		)
	}
}

// Create creates one or more tasks on a channel board.
func (handler *CollectionHandler) Create(r api.WorkspaceScopedJSON[dto.TaskCreateRequest]) (api.Response, error) {
	request := r.Body

	channelID := strings.TrimSpace(r.Gin.Param("channelId"))
	if channelID == "" {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "channelId is required")
	}

	createRequest := CreateTasksRequest{
		Context: NewUserServiceContext(r.WorkspaceID(), r.User.User.ID, r.User.User.Name),
		Board:   BoardRef{ChannelID: channelID},
	}
	if request.Task != nil {
		createRequest.Task = taskCreateInputForPort(converter.FromTaskCreateInput(request.Task))
	} else {
		titles := make([]string, 0, len(request.Tasks))
		for _, task := range request.Tasks {
			titles = append(titles, task.Title)
		}
		createRequest.Titles = titles
	}

	response, err := handler.taskBoard.CreateTasks(r.Context(), createRequest)
	if err != nil {
		return api.Response{}, err
	}

	return api.OK(dto.TaskPageResponse{Tasks: converter.ToTasksEmpty(taskboardTasksForDTO(response.Tasks))}), nil
}
