package run

import (
	"encoding/base64"
	"encoding/json"
	"net/http"
	"strconv"
	"strings"

	"github.com/tidbcloud/AgentTeam/internal/api"
	"github.com/tidbcloud/AgentTeam/internal/workflow/runartifact"
)

// ReadArtifact serves the same bounded read surface for canonical oversized
// Join/Fan-out values that the Run detail exposes as typed references. The
// complete reference is supplied in an opaque URL-safe query value; artifactId
// by itself is intentionally insufficient.
func (handler *Handler) ReadArtifact(request api.WorkspaceScopedRequest) (api.Response, error) {
	runID, err := requestRunID(request)
	if err != nil {
		return api.Response{}, err
	}
	rawReference := strings.TrimSpace(request.Gin.Query("reference"))
	if rawReference == "" || len(rawReference) > runartifact.MaxCursorBytes {
		return api.Response{}, publicError(http.StatusBadRequest, "run_invalid_request", "reference is required")
	}
	encoded, err := base64.RawURLEncoding.DecodeString(rawReference)
	if err != nil {
		return api.Response{}, publicError(http.StatusBadRequest, "run_invalid_request", "reference is invalid")
	}
	var reference runartifact.Ref
	decoder := json.NewDecoder(strings.NewReader(string(encoded)))
	decoder.DisallowUnknownFields()
	if err := decoder.Decode(&reference); err != nil {
		return api.Response{}, publicError(http.StatusBadRequest, "run_invalid_request", "reference is invalid")
	}
	if err := reference.Validate(); err != nil {
		return api.Response{}, publicError(http.StatusBadRequest, "run_invalid_request", "reference is invalid")
	}
	section := strings.TrimSpace(request.Gin.Query("section"))
	if section == "" {
		section = "root"
	}
	path := request.Gin.QueryArray("path")
	cursor := strings.TrimSpace(request.Gin.Query("cursor"))
	limit := runartifact.DefaultPageBytes
	if rawLimit := strings.TrimSpace(request.Gin.Query("limit")); rawLimit != "" {
		limit, err = strconv.Atoi(rawLimit)
		if err != nil || limit < 1 || limit > runartifact.MaxPageBytes {
			return api.Response{}, publicError(http.StatusBadRequest, "run_invalid_request", "limit is invalid")
		}
	}
	reader, ok := handler.service.(ArtifactReader)
	if !ok {
		return api.Response{}, publicError(http.StatusInternalServerError, "run_artifact_unavailable", "artifact reads are unavailable")
	}
	page, err := reader.ReadArtifactPage(request.Context(), ArtifactReadInput{
		WorkspaceID: request.WorkspaceID(), RunID: runID, Reference: reference,
		Section: section, Path: path, Cursor: cursor, Limit: limit,
	})
	if err != nil {
		return api.Response{}, err
	}
	return api.OK(map[string]any{
		"reference": page.Reference, "section": page.Section, "path": page.Path,
		"bytes": page.Bytes, "offset": page.Offset, "totalBytes": page.TotalBytes,
		"nextCursor": page.NextCursor,
	}), nil
}
