package exec

import (
	"context"
	"io"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/tidbcloud/AgentTeam/desktop/internal/wire/apiclient"
)

// TestApiclientProjectAPI exercises the typed project client transport, including
// authentication, wire-field mapping, path escaping, and missing credentials.
func TestApiclientProjectAPI(t *testing.T) {
	var method, path, body, auth string
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		method, path, auth = r.Method, r.URL.Path, r.Header.Get("Authorization")
		if r.Body != nil {
			b, _ := io.ReadAll(r.Body)
			body = string(b)
		}
		switch r.Method {
		case http.MethodGet:
			io.WriteString(w, `{"projects":[{"id":"p1","rootPath":"/x","name":"X"}]}`)
		case http.MethodPost:
			io.WriteString(w, `{"project":{"id":"p2","rootPath":"/y","name":"Y"}}`)
		case http.MethodDelete:
			w.WriteHeader(http.StatusNoContent)
		}
	}))
	defer srv.Close()

	client := func() *apiclient.Client {
		return &apiclient.Client{ServerURL: srv.URL, AgentID: "ag", AuthToken: "tok", RouteWorkspaceID: "ws", HTTPClient: srv.Client()}
	}
	api := projectRemote{client: client()}

	t.Run("list GET /projects with bearer, DTO mapped", func(t *testing.T) {
		method, path, auth = "", "", ""
		got, err := api.list(context.Background())
		if err != nil {
			t.Fatal(err)
		}
		if method != http.MethodGet || !strings.Contains(path, "/projects") {
			t.Errorf("list req: %s %s", method, path)
		}
		if !strings.Contains(auth, "tok") {
			t.Errorf("missing bearer: %q", auth)
		}
		if len(got) != 1 || got[0].ID != "p1" || got[0].RootPath != "/x" {
			t.Errorf("list DTO: %+v", got)
		}
	})
	t.Run("create POSTs camelCase body, no machineId", func(t *testing.T) {
		method, body = "", ""
		p, err := api.create(context.Background(), projectCreateRequest{RootPath: "/r", Name: "N"})
		if err != nil {
			t.Fatal(err)
		}
		if method != http.MethodPost {
			t.Errorf("method %s", method)
		}
		if !strings.Contains(body, `"rootPath":"/r"`) || !strings.Contains(body, `"name":"N"`) {
			t.Errorf("create body missing camelCase fields: %s", body)
		}
		if strings.Contains(body, "machineId") {
			t.Errorf("create body leaked machineId: %s", body)
		}
		if strings.Contains(body, "root_path") {
			t.Errorf("create body leaked legacy root_path: %s", body)
		}
		if p.ID != "p2" {
			t.Errorf("create DTO: %+v", p)
		}
	})
	t.Run("delete DELETE with escaped id in path", func(t *testing.T) {
		method, path = "", ""
		if err := api.delete(context.Background(), "prj_1"); err != nil {
			t.Fatal(err)
		}
		if method != http.MethodDelete || !strings.Contains(path, "/projects/prj_1") {
			t.Errorf("delete req: %s %s", method, path)
		}
	})
	t.Run("missing credentials fails stably", func(t *testing.T) {
		empty := projectRemote{client: &apiclient.Client{ServerURL: srv.URL, RouteWorkspaceID: "ws"}}
		if _, err := empty.list(context.Background()); err == nil {
			t.Fatal("expected stable credential failure")
		}
	})
}
