package client

import (
	"context"
	"io"
	"net/url"
)

// ContainerStatsOptions holds parameters to retrieve container statistics
// using the [Client.ContainerStats] method.
type ContainerStatsOptions struct {
	// Stream enables streaming [container.StatsResponse] results instead
	// of collecting a single sample. If enabled, the client remains attached
	// until the [ContainerStatsResult.Body] is closed or the context is
	// cancelled.
	Stream bool

	// IncludePreviousSample asks the daemon to  collect a prior sample to populate the
	// [container.StatsResponse.PreRead] and [container.StatsResponse.PreCPUStats]
	// fields.
	//
	// It set, the daemon collects two samples at a one-second interval before
	// returning the result. The first sample populates the PreCPUStats (“previous
	// CPU”) field, allowing delta calculations for CPU usage. If false, only
	// a single sample is taken and returned immediately, leaving PreRead and
	// PreCPUStats empty.
	//
	// This option has no effect if Stream is enabled. If Stream is enabled,
	// [container.StatsResponse.PreCPUStats] is never populated for the first
	// record.
	IncludePreviousSample bool
}

// ContainerStatsResult holds the result from [Client.ContainerStats].
//
// It wraps an [io.ReadCloser] that provides one or more [container.StatsResponse]
// objects for a container, as produced by the "GET /containers/{id}/stats" endpoint.
// If streaming is disabled, the stream contains a single record.
type ContainerStatsResult struct {
	Body io.ReadCloser
}

// ContainerStats retrieves live resource usage statistics for the specified
// container. The caller must close the [io.ReadCloser] in the returned result
// to release associated resources.
//
// The underlying [io.ReadCloser] is automatically closed if the context is canceled,
func (cli *Client) ContainerStats(ctx context.Context, containerID string, options ContainerStatsOptions) (ContainerStatsResult, error) {
	containerID, err := trimID("container", containerID)
	if err != nil {
		return ContainerStatsResult{}, err
	}

	query := url.Values{}
	if options.Stream {
		query.Set("stream", "true")
	} else {
		// Note: daemons before v29.0 return an error if both set: "cannot have stream=true and one-shot=true"
		//
		// TODO(thaJeztah): consider making "stream=false" the default for the API as well, or using Accept Header to switch.
		query.Set("stream", "false")
		if !options.IncludePreviousSample {
			query.Set("one-shot", "true")
		}
	}

	resp, err := cli.get(ctx, "/containers/"+containerID+"/stats", query, nil)
	if err != nil {
		return ContainerStatsResult{}, err
	}

	return ContainerStatsResult{
		Body: newCancelReadCloser(ctx, resp.Body),
	}, nil
}
