package task

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

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

// RelatedTasksForThread handles GET /api/tasks/related/thread/:threadChannelId.
// It returns tasks explicitly sourced from the thread plus their direct child
// subtasks.
func (handler *BrowseHandler) RelatedTasksForThread(r api.WorkspaceScopedRequest) (api.Response, error) {
	authenticated := r.User
	workspaceID := r.WorkspaceID()

	threadChannelID := strings.TrimSpace(r.Gin.Param("threadChannelId"))
	if threadChannelID == "" {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "threadChannelId is required")
	}
	params, err := parseRelatedTaskListParams(r)
	if err != nil {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, err.Error())
	}

	response, err := handler.taskBoard.ListRelatedTasksForThread(r.Context(), ListRelatedTasksForThreadRequest{
		Context:         NewUserServiceContext(workspaceID, authenticated.User.ID, authenticated.User.Name),
		ThreadChannelID: threadChannelID,
		Limit:           params.limit,
		Cursor:          params.cursor,
		Status:          params.status,
	})
	if err != nil {
		return api.Response{}, err
	}
	overlayRelatedTaskUnread(handler.unreadRuntime, workspaceID, r.Workspace.MemberID, response.Tasks)

	return api.OK(converter.ToRelatedTasksResponse(taskboardRelatedTasksResponseForDTO(response))), nil
}

// RelatedTasksSummaryForThread handles GET /api/tasks/related/thread/:threadChannelId/summary.
// It returns the FULL-COUNT status distribution (taskCount + statusCounts) of
// all tasks related to the thread, independent of pagination.
func (handler *BrowseHandler) RelatedTasksSummaryForThread(r api.WorkspaceScopedRequest) (api.Response, error) {
	authenticated := r.User
	workspaceID := r.WorkspaceID()

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

	response, err := handler.taskBoard.RelatedTasksSummaryForThread(r.Context(), RelatedTasksSummaryForThreadRequest{
		Context:         NewUserServiceContext(workspaceID, authenticated.User.ID, authenticated.User.Name),
		ThreadChannelID: threadChannelID,
	})
	if err != nil {
		return api.Response{}, err
	}

	return api.OK(relatedTasksSummaryResponseForDTO(response)), nil
}

// RelatedExecutionTasksForAgent handles GET /api/tasks/related/agents/:agentId/execution.
// It returns tasks assigned to the agent. Creation, mention, review history,
// and other historical links are intentionally excluded.
func (handler *BrowseHandler) RelatedExecutionTasksForAgent(r api.WorkspaceScopedRequest) (api.Response, error) {
	authenticated := r.User
	workspaceID := r.WorkspaceID()

	agentID := strings.TrimSpace(r.Gin.Param("agentId"))
	if agentID == "" {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "agentId is required")
	}
	params, err := parseRelatedTaskListParams(r)
	if err != nil {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, err.Error())
	}

	response, err := handler.taskBoard.ListRelatedExecutionTasksForAgent(r.Context(), ListRelatedExecutionTasksForAgentRequest{
		Context: NewUserServiceContext(workspaceID, authenticated.User.ID, authenticated.User.Name),
		AgentID: agentID,
		Limit:   params.limit,
		Cursor:  params.cursor,
		Status:  params.status,
	})
	if err != nil {
		return api.Response{}, err
	}
	overlayRelatedTaskUnread(handler.unreadRuntime, workspaceID, r.Workspace.MemberID, response.Tasks)

	return api.OK(converter.ToRelatedTasksResponse(taskboardRelatedTasksResponseForDTO(response))), nil
}

// RelatedExecutionTasksSummaryForAgent handles GET /api/tasks/related/agents/:agentId/execution/summary.
// It returns the FULL-COUNT status distribution (taskCount + statusCounts) of all
// agent execution tasks, independent of pagination.
func (handler *BrowseHandler) RelatedExecutionTasksSummaryForAgent(r api.WorkspaceScopedRequest) (api.Response, error) {
	authenticated := r.User
	workspaceID := r.WorkspaceID()

	agentID := strings.TrimSpace(r.Gin.Param("agentId"))
	if agentID == "" {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "agentId is required")
	}
	params, err := parseRelatedTaskListParams(r)
	if err != nil {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, err.Error())
	}

	response, err := handler.taskBoard.RelatedExecutionTasksSummaryForAgent(r.Context(), RelatedExecutionTasksSummaryForAgentRequest{
		Context: NewUserServiceContext(workspaceID, authenticated.User.ID, authenticated.User.Name),
		AgentID: agentID,
		Limit:   params.limit,
		Cursor:  params.cursor,
		Status:  params.status,
	})
	if err != nil {
		return api.Response{}, err
	}

	return api.OK(relatedTasksSummaryResponseForDTO(response)), nil
}

type relatedTaskListParams struct {
	limit  int
	cursor RelatedTaskCursor
	status string
}

func parseRelatedTaskListParams(r api.WorkspaceScopedRequest) (relatedTaskListParams, error) {
	var params relatedTaskListParams
	if rawLimit := strings.TrimSpace(r.Gin.Query("limit")); rawLimit != "" {
		limit, err := strconv.Atoi(rawLimit)
		if err != nil {
			return relatedTaskListParams{}, badRequest("limit must be an integer")
		}
		params.limit = limit
	}
	if rawCursor := strings.TrimSpace(r.Gin.Query("cursor")); rawCursor != "" {
		cursor, err := converter.FromRelatedTaskCursorToken(rawCursor)
		if err != nil {
			return relatedTaskListParams{}, badRequest(err.Error())
		}
		params.cursor = RelatedTaskCursor{TaskNumber: cursor.TaskNumber, TaskID: cursor.TaskID}
	}
	params.status = strings.TrimSpace(r.Gin.Query("status"))
	return params, nil
}
