package hub

// S3 Group C — RegisterWG client (POST /hosts/{id}/wg, per-host key). Typed-error mapping and
// the no-token-in-errors invariant, same scaffolding as the desired-state client tests.

import (
	"context"
	"errors"
	"io"
	"net/http"
	"strings"
	"testing"
)

func TestRegisterWG_PathAuthBodyAndDecode(t *testing.T) {
	var gotPath, gotAuth, gotMethod, gotBody string
	c := testClient(func(r *http.Request) (*http.Response, error) {
		gotPath = r.URL.Path
		gotAuth = r.Header.Get("Authorization")
		gotMethod = r.Method
		b, _ := io.ReadAll(r.Body)
		gotBody = string(b)
		return httpResp(200, `{"pubkey":"PK","assigned_ip":"10.77.0.2/32","existed":false,"generation":3,"sync":"ok"}`), nil
	})

	resp, err := c.RegisterWG(context.Background(), "PK")
	if err != nil {
		t.Fatalf("RegisterWG: %v", err)
	}
	if gotMethod != http.MethodPost || gotPath != "/api/v1/hosts/demo-host-01/wg" {
		t.Errorf("request = %s %s, want POST /api/v1/hosts/demo-host-01/wg", gotMethod, gotPath)
	}
	if gotAuth != "Bearer super-secret-bearer-key" {
		t.Errorf("auth = %q", gotAuth)
	}
	if gotBody != `{"pubkey":"PK"}` {
		t.Errorf("body = %s", gotBody)
	}
	if resp.AssignedIP != "10.77.0.2/32" || resp.Existed || resp.Generation != 3 || resp.Sync != "ok" {
		t.Errorf("resp = %+v", resp)
	}
}

func TestRegisterWG_TypedErrors(t *testing.T) {
	for _, tc := range []struct {
		status int
		body   string
	}{
		{403, "Forbidden: host_id mismatch"},
		{404, "Unknown host_id"},
		{409, "wg endpoint not configured"},
		{409, "pubkey already registered elsewhere"},
	} {
		c := testClient(func(r *http.Request) (*http.Response, error) {
			return httpResp(tc.status, tc.body), nil
		})
		_, err := c.RegisterWG(context.Background(), "PK")
		var he *HTTPError
		if !errors.As(err, &he) || he.StatusCode != tc.status {
			t.Errorf("status %d: err = %v, want HTTPError %d", tc.status, err, tc.status)
		}
		if strings.Contains(err.Error(), "super-secret-bearer-key") {
			t.Fatalf("bearer token leaked into error: %v", err)
		}
	}
	// Transport failure → TransportError, token-free.
	c := testClient(func(r *http.Request) (*http.Response, error) {
		return nil, errors.New("dial tcp: connection refused")
	})
	_, err := c.RegisterWG(context.Background(), "PK")
	var te *TransportError
	if !errors.As(err, &te) {
		t.Errorf("transport err = %v, want TransportError", err)
	}
}
