package claudebox

import (
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/http/httptest"
	"strings"
	"sync"
	"testing"
	"time"
)

func TestNewClient_DefaultTimeout(t *testing.T) {
	client := NewClient(ClientConfig{
		BaseURL: "http://localhost:8080",
	})

	if client.httpClient.Timeout != 10*time.Minute {
		t.Errorf("expected default timeout 10m, got %v", client.httpClient.Timeout)
	}
}

func TestNewClient_CustomTimeout(t *testing.T) {
	client := NewClient(ClientConfig{
		BaseURL: "http://localhost:8080",
		Timeout: 5 * time.Minute,
	})

	if client.httpClient.Timeout != 5*time.Minute {
		t.Errorf("expected timeout 5m, got %v", client.httpClient.Timeout)
	}
}

func TestNewClient_TrimsTrailingSlash(t *testing.T) {
	client := NewClient(ClientConfig{
		BaseURL: "http://localhost:8080/",
	})

	if client.baseURL != "http://localhost:8080" {
		t.Errorf("expected trailing slash trimmed, got %s", client.baseURL)
	}
}

func TestHealth_Success(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodGet {
			t.Errorf("expected GET, got %s", r.Method)
		}
		if r.URL.Path != "/health" {
			t.Errorf("expected /health, got %s", r.URL.Path)
		}

		resp := HealthResponse{
			Status:    "healthy",
			Timestamp: "2024-01-15T10:30:00Z",
			WorkDir:   "/workspace",
		}
		w.Header().Set("Content-Type", "application/json")
		_ = json.NewEncoder(w).Encode(resp)
	}))
	defer server.Close()

	client := NewClient(ClientConfig{BaseURL: server.URL})

	health, err := client.Health(context.Background())

	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if health.Status != "healthy" {
		t.Errorf("expected status 'healthy', got %s", health.Status)
	}
	if health.WorkDir != "/workspace" {
		t.Errorf("expected work_dir '/workspace', got %s", health.WorkDir)
	}
}

func TestHealth_Unhealthy(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusServiceUnavailable)
	}))
	defer server.Close()

	client := NewClient(ClientConfig{BaseURL: server.URL})

	_, err := client.Health(context.Background())

	if err == nil {
		t.Fatal("expected error, got nil")
	}
	if !strings.Contains(err.Error(), "health check returned status 503") {
		t.Errorf("expected 503 error, got %v", err)
	}
}

func TestHealth_NetworkError(t *testing.T) {
	client := NewClient(ClientConfig{
		BaseURL: "http://localhost:1",
		Timeout: 100 * time.Millisecond,
	})

	_, err := client.Health(context.Background())

	if err == nil {
		t.Fatal("expected error, got nil")
	}
	if !strings.Contains(err.Error(), "health check:") {
		t.Errorf("expected error wrapped with 'health check:', got %v", err)
	}
}

func TestExecute_Success(t *testing.T) {
	var receivedReq ExecuteRequest
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			t.Errorf("expected POST, got %s", r.Method)
		}
		if r.URL.Path != "/execute" {
			t.Errorf("expected /execute, got %s", r.URL.Path)
		}
		if r.Header.Get("Content-Type") != "application/json" {
			t.Errorf("expected Content-Type application/json, got %s", r.Header.Get("Content-Type"))
		}

		body, _ := io.ReadAll(r.Body)
		_ = json.Unmarshal(body, &receivedReq)

		resp := ExecuteResponse{
			Success:    true,
			Output:     "Task completed",
			ExitCode:   0,
			DurationMs: 5000,
			SessionID:  "session-123",
		}
		w.Header().Set("Content-Type", "application/json")
		_ = json.NewEncoder(w).Encode(resp)
	}))
	defer server.Close()

	client := NewClient(ClientConfig{BaseURL: server.URL})

	req := &ExecuteRequest{
		Prompt:       "Build the project",
		AllowedTools: []string{"Bash", "Read", "Write"},
		WorkingDir:   "/workspace/project",
		Timeout:      300,
		Metadata:     map[string]string{"task_id": "task-1"},
	}

	result, err := client.Execute(context.Background(), req)

	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !result.Success {
		t.Error("expected success=true")
	}
	if result.Output != "Task completed" {
		t.Errorf("expected output 'Task completed', got %s", result.Output)
	}
	if result.ExitCode != 0 {
		t.Errorf("expected exit code 0, got %d", result.ExitCode)
	}

	// Verify request was serialized correctly
	if receivedReq.Prompt != "Build the project" {
		t.Errorf("expected prompt 'Build the project', got %s", receivedReq.Prompt)
	}
	if len(receivedReq.AllowedTools) != 3 {
		t.Errorf("expected 3 allowed tools, got %d", len(receivedReq.AllowedTools))
	}
}

func TestExecute_ErrorStatus(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusBadRequest)
		_, _ = w.Write([]byte(`{"error":"invalid prompt"}`))
	}))
	defer server.Close()

	client := NewClient(ClientConfig{BaseURL: server.URL})

	_, err := client.Execute(context.Background(), &ExecuteRequest{Prompt: ""})

	if err == nil {
		t.Fatal("expected error, got nil")
	}
	if !strings.Contains(err.Error(), "execute returned status 400") {
		t.Errorf("expected 400 error, got %v", err)
	}
	if !strings.Contains(err.Error(), "invalid prompt") {
		t.Errorf("expected error body in message, got %v", err)
	}
}

func TestExecute_MalformedResponse(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		_, _ = w.Write([]byte(`{invalid json`))
	}))
	defer server.Close()

	client := NewClient(ClientConfig{BaseURL: server.URL})

	_, err := client.Execute(context.Background(), &ExecuteRequest{Prompt: "test"})

	if err == nil {
		t.Fatal("expected error, got nil")
	}
	if !strings.Contains(err.Error(), "decode response") {
		t.Errorf("expected decode error, got %v", err)
	}
}

func TestExecuteStream_Success(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			t.Errorf("expected POST, got %s", r.Method)
		}
		if r.URL.Path != "/execute/stream" {
			t.Errorf("expected /execute/stream, got %s", r.URL.Path)
		}
		if r.Header.Get("Accept") != "text/event-stream" {
			t.Errorf("expected Accept text/event-stream, got %s", r.Header.Get("Accept"))
		}

		w.Header().Set("Content-Type", "text/event-stream")
		w.Header().Set("Cache-Control", "no-cache")
		w.Header().Set("Connection", "keep-alive")

		flusher, ok := w.(http.Flusher)
		if !ok {
			t.Fatal("expected http.Flusher")
		}

		events := []StreamEvent{
			{Type: "start", Timestamp: "2024-01-15T10:30:00Z"},
			{Type: "output", Content: "Building...", Timestamp: "2024-01-15T10:30:01Z"},
			{Type: "tool_call", ToolName: "Bash", Timestamp: "2024-01-15T10:30:02Z"},
			{Type: "complete", Content: "Done", Timestamp: "2024-01-15T10:30:05Z"},
		}

		for _, event := range events {
			data, _ := json.Marshal(event)
			fmt.Fprintf(w, "data: %s\n\n", data)
			flusher.Flush()
		}
	}))
	defer server.Close()

	client := NewClient(ClientConfig{BaseURL: server.URL})

	var receivedEvents []StreamEvent
	var mu sync.Mutex

	err := client.ExecuteStream(context.Background(), &ExecuteRequest{Prompt: "build"}, func(event StreamEvent) {
		mu.Lock()
		receivedEvents = append(receivedEvents, event)
		mu.Unlock()
	})

	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	if len(receivedEvents) != 4 {
		t.Fatalf("expected 4 events, got %d", len(receivedEvents))
	}
	if receivedEvents[0].Type != "start" {
		t.Errorf("expected first event type 'start', got %s", receivedEvents[0].Type)
	}
	if receivedEvents[1].Content != "Building..." {
		t.Errorf("expected second event content 'Building...', got %s", receivedEvents[1].Content)
	}
	if receivedEvents[2].ToolName != "Bash" {
		t.Errorf("expected third event tool name 'Bash', got %s", receivedEvents[2].ToolName)
	}
}

func TestExecuteStream_SkipsMalformedEvents(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/event-stream")

		flusher, _ := w.(http.Flusher)

		// Valid event
		event1, _ := json.Marshal(StreamEvent{Type: "start"})
		fmt.Fprintf(w, "data: %s\n\n", event1)
		flusher.Flush()

		// Malformed JSON - should be skipped
		fmt.Fprintf(w, "data: {invalid json}\n\n")
		flusher.Flush()

		// Empty data - should be skipped
		fmt.Fprintf(w, "data: \n\n")
		flusher.Flush()

		// Non-data line - should be skipped
		fmt.Fprintf(w, "event: ping\n\n")
		flusher.Flush()

		// Valid event
		event2, _ := json.Marshal(StreamEvent{Type: "complete"})
		fmt.Fprintf(w, "data: %s\n\n", event2)
		flusher.Flush()
	}))
	defer server.Close()

	client := NewClient(ClientConfig{BaseURL: server.URL})

	var receivedEvents []StreamEvent
	var mu sync.Mutex

	err := client.ExecuteStream(context.Background(), &ExecuteRequest{Prompt: "test"}, func(event StreamEvent) {
		mu.Lock()
		receivedEvents = append(receivedEvents, event)
		mu.Unlock()
	})

	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	// Should only receive the 2 valid events
	if len(receivedEvents) != 2 {
		t.Fatalf("expected 2 events (malformed skipped), got %d", len(receivedEvents))
	}
	if receivedEvents[0].Type != "start" {
		t.Errorf("expected first event 'start', got %s", receivedEvents[0].Type)
	}
	if receivedEvents[1].Type != "complete" {
		t.Errorf("expected second event 'complete', got %s", receivedEvents[1].Type)
	}
}

func TestExecuteStream_ErrorStatus(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusInternalServerError)
		_, _ = w.Write([]byte(`{"error":"agent unavailable"}`))
	}))
	defer server.Close()

	client := NewClient(ClientConfig{BaseURL: server.URL})

	err := client.ExecuteStream(context.Background(), &ExecuteRequest{Prompt: "test"}, func(event StreamEvent) {
		t.Error("handler should not be called on error")
	})

	if err == nil {
		t.Fatal("expected error, got nil")
	}
	if !strings.Contains(err.Error(), "execute stream returned status 500") {
		t.Errorf("expected 500 error, got %v", err)
	}
}

func TestExecuteStream_ContextCanceledBeforeRequest(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		t.Error("handler should not be called when context is already canceled")
	}))
	defer server.Close()

	client := NewClient(ClientConfig{BaseURL: server.URL})

	// Cancel context before making request
	ctx, cancel := context.WithCancel(context.Background())
	cancel()

	err := client.ExecuteStream(ctx, &ExecuteRequest{Prompt: "test"}, func(event StreamEvent) {})

	if err == nil {
		t.Fatal("expected error, got nil")
	}
	// Should get a context canceled error
}

func TestGitClone_Success(t *testing.T) {
	var receivedReq GitCloneRequest
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			t.Errorf("expected POST, got %s", r.Method)
		}
		if r.URL.Path != "/git/clone" {
			t.Errorf("expected /git/clone, got %s", r.URL.Path)
		}

		body, _ := io.ReadAll(r.Body)
		_ = json.Unmarshal(body, &receivedReq)

		resp := GitCloneResponse{
			Success: true,
			Cloned:  true,
		}
		w.Header().Set("Content-Type", "application/json")
		_ = json.NewEncoder(w).Encode(resp)
	}))
	defer server.Close()

	client := NewClient(ClientConfig{BaseURL: server.URL})

	result, err := client.GitClone(context.Background(), "https://github.com/example/repo.git", "/workspace")

	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !result.Success {
		t.Error("expected success=true")
	}
	if !result.Cloned {
		t.Error("expected cloned=true")
	}
	if receivedReq.CloneURL != "https://github.com/example/repo.git" {
		t.Errorf("expected clone URL, got %s", receivedReq.CloneURL)
	}
	if receivedReq.WorkDir != "/workspace" {
		t.Errorf("expected work dir '/workspace', got %s", receivedReq.WorkDir)
	}
}

func TestGitClone_AlreadyExists(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		resp := GitCloneResponse{
			Success: true,
			Cloned:  false, // Already existed, just updated
		}
		w.Header().Set("Content-Type", "application/json")
		_ = json.NewEncoder(w).Encode(resp)
	}))
	defer server.Close()

	client := NewClient(ClientConfig{BaseURL: server.URL})

	result, err := client.GitClone(context.Background(), "https://github.com/example/repo.git", "/workspace")

	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !result.Success {
		t.Error("expected success=true")
	}
	if result.Cloned {
		t.Error("expected cloned=false for existing repo")
	}
}

func TestGitClone_ErrorStatus(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusBadRequest)
		_, _ = w.Write([]byte(`{"error":"invalid clone URL"}`))
	}))
	defer server.Close()

	client := NewClient(ClientConfig{BaseURL: server.URL})

	_, err := client.GitClone(context.Background(), "invalid", "/workspace")

	if err == nil {
		t.Fatal("expected error, got nil")
	}
	if !strings.Contains(err.Error(), "git clone returned status 400") {
		t.Errorf("expected 400 error, got %v", err)
	}
}

func TestGitCommitAndPush_Success(t *testing.T) {
	var receivedReq GitCommitAndPushRequest
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			t.Errorf("expected POST, got %s", r.Method)
		}
		if r.URL.Path != "/git/commit-and-push" {
			t.Errorf("expected /git/commit-and-push, got %s", r.URL.Path)
		}

		body, _ := io.ReadAll(r.Body)
		_ = json.Unmarshal(body, &receivedReq)

		resp := GitCommitAndPushResponse{
			Success:      true,
			HasChanges:   true,
			CommitSHA:    "abc123def456",
			FilesChanged: []string{"main.go", "go.mod"},
			Pushed:       true,
		}
		w.Header().Set("Content-Type", "application/json")
		_ = json.NewEncoder(w).Encode(resp)
	}))
	defer server.Close()

	client := NewClient(ClientConfig{BaseURL: server.URL})

	result, err := client.GitCommitAndPush(context.Background(), "feat: add feature", true, "/workspace")

	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !result.Success {
		t.Error("expected success=true")
	}
	if !result.HasChanges {
		t.Error("expected has_changes=true")
	}
	if result.CommitSHA != "abc123def456" {
		t.Errorf("expected commit SHA abc123def456, got %s", result.CommitSHA)
	}
	if !result.Pushed {
		t.Error("expected pushed=true")
	}
	if len(result.FilesChanged) != 2 {
		t.Errorf("expected 2 files changed, got %d", len(result.FilesChanged))
	}

	// Verify request
	if receivedReq.Message != "feat: add feature" {
		t.Errorf("expected message 'feat: add feature', got %s", receivedReq.Message)
	}
	if !receivedReq.Push {
		t.Error("expected push=true in request")
	}
}

func TestGitCommitAndPush_NoChanges(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		resp := GitCommitAndPushResponse{
			Success:    true,
			HasChanges: false,
		}
		w.Header().Set("Content-Type", "application/json")
		_ = json.NewEncoder(w).Encode(resp)
	}))
	defer server.Close()

	client := NewClient(ClientConfig{BaseURL: server.URL})

	result, err := client.GitCommitAndPush(context.Background(), "test", false, "/workspace")

	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !result.Success {
		t.Error("expected success=true")
	}
	if result.HasChanges {
		t.Error("expected has_changes=false")
	}
	if result.CommitSHA != "" {
		t.Errorf("expected empty commit SHA, got %s", result.CommitSHA)
	}
}

func TestGitCommitAndPush_ErrorStatus(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusInternalServerError)
		_, _ = w.Write([]byte(`{"error":"git push failed"}`))
	}))
	defer server.Close()

	client := NewClient(ClientConfig{BaseURL: server.URL})

	_, err := client.GitCommitAndPush(context.Background(), "test", true, "/workspace")

	if err == nil {
		t.Fatal("expected error, got nil")
	}
	if !strings.Contains(err.Error(), "git commit returned status 500") {
		t.Errorf("expected 500 error, got %v", err)
	}
}

func TestGitStatus_Success(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodGet {
			t.Errorf("expected GET, got %s", r.Method)
		}
		if r.URL.Path != "/git/status" {
			t.Errorf("expected /git/status, got %s", r.URL.Path)
		}
		if r.URL.Query().Get("work_dir") != "/workspace/project" {
			t.Errorf("expected work_dir query param, got %s", r.URL.Query().Get("work_dir"))
		}

		resp := GitStatusResponse{
			IsRepo:       true,
			HasChanges:   true,
			ChangedFiles: []string{"main.go", "README.md"},
			Branch:       "feature/test",
		}
		w.Header().Set("Content-Type", "application/json")
		_ = json.NewEncoder(w).Encode(resp)
	}))
	defer server.Close()

	client := NewClient(ClientConfig{BaseURL: server.URL})

	result, err := client.GitStatus(context.Background(), "/workspace/project")

	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !result.IsRepo {
		t.Error("expected is_repo=true")
	}
	if !result.HasChanges {
		t.Error("expected has_changes=true")
	}
	if result.Branch != "feature/test" {
		t.Errorf("expected branch 'feature/test', got %s", result.Branch)
	}
	if len(result.ChangedFiles) != 2 {
		t.Errorf("expected 2 changed files, got %d", len(result.ChangedFiles))
	}
}

func TestGitStatus_EmptyWorkDir(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// work_dir should not be in query when empty
		if r.URL.Query().Get("work_dir") != "" {
			t.Errorf("expected empty work_dir, got %s", r.URL.Query().Get("work_dir"))
		}

		resp := GitStatusResponse{IsRepo: true}
		w.Header().Set("Content-Type", "application/json")
		_ = json.NewEncoder(w).Encode(resp)
	}))
	defer server.Close()

	client := NewClient(ClientConfig{BaseURL: server.URL})

	_, err := client.GitStatus(context.Background(), "")

	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
}

func TestGitStatus_ErrorStatus(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusNotFound)
		_, _ = w.Write([]byte(`{"error":"not a git repository"}`))
	}))
	defer server.Close()

	client := NewClient(ClientConfig{BaseURL: server.URL})

	_, err := client.GitStatus(context.Background(), "/workspace")

	if err == nil {
		t.Fatal("expected error, got nil")
	}
	if !strings.Contains(err.Error(), "git status returned status 404") {
		t.Errorf("expected 404 error, got %v", err)
	}
}

func TestRunSDLC_Success(t *testing.T) {
	var receivedReq SDLCRequest
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost {
			t.Errorf("expected POST, got %s", r.Method)
		}
		if r.URL.Path != "/sdlc" {
			t.Errorf("expected /sdlc, got %s", r.URL.Path)
		}

		body, _ := io.ReadAll(r.Body)
		_ = json.Unmarshal(body, &receivedReq)

		resp := SDLCResponse{
			Success: true,
			Output:  "Feature started successfully",
			Data:    json.RawMessage(`{"feature_id":"feat-123"}`),
		}
		w.Header().Set("Content-Type", "application/json")
		_ = json.NewEncoder(w).Encode(resp)
	}))
	defer server.Close()

	client := NewClient(ClientConfig{BaseURL: server.URL})

	result, err := client.RunSDLC(context.Background(), "start", []string{"--name", "test-feature"}, "/workspace")

	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !result.Success {
		t.Error("expected success=true")
	}
	if result.Output != "Feature started successfully" {
		t.Errorf("expected output message, got %s", result.Output)
	}
	if result.Data == nil {
		t.Error("expected data to be set")
	}

	// Verify request
	if receivedReq.Command != "start" {
		t.Errorf("expected command 'start', got %s", receivedReq.Command)
	}
	if len(receivedReq.Args) != 2 {
		t.Errorf("expected 2 args, got %d", len(receivedReq.Args))
	}
	if receivedReq.WorkDir != "/workspace" {
		t.Errorf("expected work dir '/workspace', got %s", receivedReq.WorkDir)
	}
}

func TestRunSDLC_CommandFailed(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		resp := SDLCResponse{
			Success: false,
			Output:  "Command output before failure",
			Error:   "validation failed: missing required field",
		}
		w.Header().Set("Content-Type", "application/json")
		_ = json.NewEncoder(w).Encode(resp)
	}))
	defer server.Close()

	client := NewClient(ClientConfig{BaseURL: server.URL})

	result, err := client.RunSDLC(context.Background(), "validate", nil, "/workspace")

	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if result.Success {
		t.Error("expected success=false")
	}
	if result.Error != "validation failed: missing required field" {
		t.Errorf("expected error message, got %s", result.Error)
	}
}

func TestRunSDLC_ErrorStatus(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusInternalServerError)
		_, _ = w.Write([]byte(`{"error":"sdlc binary not found"}`))
	}))
	defer server.Close()

	client := NewClient(ClientConfig{BaseURL: server.URL})

	_, err := client.RunSDLC(context.Background(), "status", nil, "/workspace")

	if err == nil {
		t.Fatal("expected error, got nil")
	}
	if !strings.Contains(err.Error(), "sdlc returned status 500") {
		t.Errorf("expected 500 error, got %v", err)
	}
}

func TestRunSDLC_MalformedResponse(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		_, _ = w.Write([]byte(`{invalid`))
	}))
	defer server.Close()

	client := NewClient(ClientConfig{BaseURL: server.URL})

	_, err := client.RunSDLC(context.Background(), "status", nil, "/workspace")

	if err == nil {
		t.Fatal("expected error, got nil")
	}
	if !strings.Contains(err.Error(), "decode response") {
		t.Errorf("expected decode error, got %v", err)
	}
}
