package httpkit

import (
	"context"
	"errors"
	"fmt"
	"io"
	"net/http"
)

// Download fetches a URL and returns the response body as bytes.
// maxBytes limits the response size; 0 means no limit.
//
// Unlike Do, Download does not apply default headers (download URLs are
// typically pre-signed or public), does not marshal JSON, and does not
// retry. It does respect the client's timeout.
func (c *Client) Download(ctx context.Context, url string, maxBytes int64) ([]byte, error) {
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
	if err != nil {
		return nil, fmt.Errorf("create download request: %w", err)
	}

	resp, err := c.http.Do(req)
	if err != nil {
		if errors.Is(err, context.DeadlineExceeded) || isTimeoutError(err) {
			return nil, fmt.Errorf("download: %w", ErrTimeout)
		}
		return nil, fmt.Errorf("download: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(io.LimitReader(resp.Body, 1024))
		return nil, &APIError{
			StatusCode: resp.StatusCode,
			Body:       string(body),
			sentinel:   ClassifyStatus(resp.StatusCode),
		}
	}

	var reader io.Reader = resp.Body
	if maxBytes > 0 {
		reader = io.LimitReader(resp.Body, maxBytes+1)
	}

	data, err := io.ReadAll(reader)
	if err != nil {
		return nil, fmt.Errorf("read download body: %w", err)
	}

	if maxBytes > 0 && int64(len(data)) > maxBytes {
		return nil, fmt.Errorf("download exceeds %d byte limit", maxBytes)
	}

	return data, nil
}
