package report

import (
	"errors"
	"fmt"
	"io"
	"net/http"
	"strings"
	"time"
)

// Config-pull error types for setup-wizard UI display.
//
// These (and PullConfig) were previously part of infra_pull.go alongside the
// disk-tier DR-recovery (PullRecovery / infra-backup) client. Disk recovery moved
// to the host agent in slice 8C; only the fresh-install config download survives
// here, so it lives in this slimmed file.
var (
	ErrHubUnreachable = errors.New("hub unreachable")
	ErrAuthFailed     = errors.New("authentication failed")
	ErrNotFound       = errors.New("customer not found")
	ErrHubError       = errors.New("hub error")
)

// PullConfig fetches a generated controller.yaml from the Hub config endpoint.
// Auth: X-Retrieval-Password header. Used by the setup wizard's fresh-install flow.
func PullConfig(hubURL, customerID, retrievalPassword string) (string, error) {
	url := strings.TrimRight(hubURL, "/") + "/api/v1/config/" + customerID

	client := &http.Client{Timeout: 30 * time.Second}

	req, err := http.NewRequest(http.MethodGet, url, nil)
	if err != nil {
		return "", fmt.Errorf("%w: %v", ErrHubError, err)
	}
	req.Header.Set("X-Retrieval-Password", retrievalPassword)

	resp, err := client.Do(req)
	if err != nil {
		return "", fmt.Errorf("%w: %v", ErrHubUnreachable, err)
	}
	defer resp.Body.Close()

	switch resp.StatusCode {
	case http.StatusOK:
		// success
	case http.StatusUnauthorized:
		return "", ErrAuthFailed
	case http.StatusNotFound:
		return "", ErrNotFound
	default:
		return "", fmt.Errorf("%w: HTTP %d", ErrHubError, resp.StatusCode)
	}

	body, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20)) // 1MB limit
	if err != nil {
		return "", fmt.Errorf("%w: reading response: %v", ErrHubError, err)
	}

	return string(body), nil
}
