package webagent

import (
	"context"
	"errors"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/tidbcloud/AgentTeam/internal/api"
	"github.com/tidbcloud/AgentTeam/internal/runtimecontrol"
)

const (
	defaultTrajectoryHistoryLimit = 200
	maxTrajectoryHistoryLimit     = 512
	trajectoryHistoryTimeout      = 10 * time.Second
)

// History handles GET /api/v1/workspaces/:workspaceId/agents/:agentId/trajectory.
func (handler *TrajectoryHandler) History(r api.WorkspaceScopedRequest) (api.Response, error) {
	agentID := strings.TrimSpace(r.Gin.Param("agentId"))
	if agentID == "" {
		return api.Response{}, api.NewHTTPError(http.StatusBadRequest, "agentId is required")
	}

	agent, err := handler.agentStore.GetAgentForUser(r.Context(), r.UserID(), r.WorkspaceID(), agentID)
	if err != nil {
		return api.Response{}, err
	}

	limit, err := parseTrajectoryHistoryLimit(r.Gin.Query("limit"))
	if err != nil {
		return api.Response{}, err
	}
	before, err := parseTrajectoryHistoryBefore(r.Gin.Query("before"))
	if err != nil {
		return api.Response{}, err
	}

	if handler.runtime == nil {
		return api.OK([]any{}), nil
	}

	requestCtx := runtimecontrol.WithRemoteRequestContext(r.Context(), runtimecontrol.RemoteRequestContext{
		Origin: runtimecontrol.RemoteRequestOriginUserInteractive,
		Cause:  runtimecontrol.RemoteRequestCauseWebAPI,
	})
	ctx, cancel := context.WithTimeout(requestCtx, trajectoryHistoryTimeout)
	defer cancel()

	items, err := handler.runtime.GetAgentTrajectoryHistory(ctx, agent.MachineID, agent.AgentID, limit, before)
	if err != nil {
		if errors.Is(err, runtimecontrol.ErrMachineOffline) {
			return api.OK([]any{}), nil
		}
		return api.Response{}, err
	}
	return api.OK(items), nil
}

func parseTrajectoryHistoryLimit(raw string) (int, error) {
	trimmed := strings.TrimSpace(raw)
	if trimmed == "" {
		return defaultTrajectoryHistoryLimit, nil
	}
	limit, err := strconv.Atoi(trimmed)
	if err != nil || limit <= 0 {
		return 0, api.NewHTTPError(http.StatusBadRequest, "limit must be a positive integer")
	}
	if limit > maxTrajectoryHistoryLimit {
		return maxTrajectoryHistoryLimit, nil
	}
	return limit, nil
}

func parseTrajectoryHistoryBefore(raw string) (int64, error) {
	trimmed := strings.TrimSpace(raw)
	if trimmed == "" {
		return 0, nil
	}
	before, err := strconv.ParseInt(trimmed, 10, 64)
	if err != nil || before < 0 {
		return 0, api.NewHTTPError(http.StatusBadRequest, "before must be a non-negative integer")
	}
	return before, nil
}
