package handlers

import (
	"bytes"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/go-chi/chi/v5"
	"github.com/orchard9/rdev/internal/domain"
	"github.com/orchard9/rdev/internal/sdlc"
	"github.com/orchard9/rdev/internal/service"
)

func setupOrchestratorHandler(exec *testSDLCExecutor) (*SDLCOrchestratorHandler, *chi.Mux) {
	repo := &testSDLCProjectRepo{
		project: &domain.Project{ID: "test-project", PodName: "test-pod"},
	}
	sdlcSvc := service.NewSDLCService(exec, repo)

	orchestrator := service.NewSDLCOrchestratorService(
		sdlcSvc,
		nil, // no agent registry for handler tests
		nil, // no git committer for handler tests
		repo,
	)

	handler := NewSDLCOrchestratorHandler(orchestrator)
	r := chi.NewRouter()
	r.Use(testAdminAuth)
	handler.Mount(r)
	return handler, r
}

func TestSDLCOrchestratorHandler_Execute(t *testing.T) {
	exec := &testSDLCExecutor{
		classification: &sdlc.Classification{
			Action:  sdlc.ActionIdle,
			Feature: "auth-flow",
			Message: "No action needed",
		},
	}
	_, router := setupOrchestratorHandler(exec)

	body, _ := json.Marshal(service.ExecuteRequest{Feature: "auth-flow"})
	req := httptest.NewRequest(http.MethodPost, "/projects/test-project/sdlc/execute", bytes.NewReader(body))
	req.Header.Set("Content-Type", "application/json")
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	if w.Code != http.StatusOK {
		t.Errorf("expected status 200, got %d: %s", w.Code, w.Body.String())
	}
}

func TestSDLCOrchestratorHandler_Execute_MissingFeature(t *testing.T) {
	exec := &testSDLCExecutor{}
	_, router := setupOrchestratorHandler(exec)

	body, _ := json.Marshal(service.ExecuteRequest{})
	req := httptest.NewRequest(http.MethodPost, "/projects/test-project/sdlc/execute", bytes.NewReader(body))
	req.Header.Set("Content-Type", "application/json")
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	if w.Code != http.StatusBadRequest {
		t.Errorf("expected status 400, got %d: %s", w.Code, w.Body.String())
	}
}

func TestSDLCOrchestratorHandler_Execute_InvalidBody(t *testing.T) {
	exec := &testSDLCExecutor{}
	_, router := setupOrchestratorHandler(exec)

	req := httptest.NewRequest(http.MethodPost, "/projects/test-project/sdlc/execute", bytes.NewReader([]byte("not json")))
	req.Header.Set("Content-Type", "application/json")
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	if w.Code != http.StatusBadRequest {
		t.Errorf("expected status 400, got %d: %s", w.Code, w.Body.String())
	}
}

func TestSDLCOrchestratorHandler_Execute_FeatureNotFound(t *testing.T) {
	exec := &testSDLCExecutor{err: sdlc.ErrFeatureNotFound}
	_, router := setupOrchestratorHandler(exec)

	body, _ := json.Marshal(service.ExecuteRequest{Feature: "nonexistent"})
	req := httptest.NewRequest(http.MethodPost, "/projects/test-project/sdlc/execute", bytes.NewReader(body))
	req.Header.Set("Content-Type", "application/json")
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	if w.Code != http.StatusNotFound {
		t.Errorf("expected status 404, got %d: %s", w.Code, w.Body.String())
	}
}

func TestSDLCOrchestratorHandler_Execute_Transition(t *testing.T) {
	exec := &testSDLCExecutor{
		classification: &sdlc.Classification{
			Action:       sdlc.ActionTransition,
			Feature:      "auth-flow",
			TransitionTo: sdlc.PhaseSpecified,
		},
	}
	_, router := setupOrchestratorHandler(exec)

	body, _ := json.Marshal(service.ExecuteRequest{Feature: "auth-flow"})
	req := httptest.NewRequest(http.MethodPost, "/projects/test-project/sdlc/execute", bytes.NewReader(body))
	req.Header.Set("Content-Type", "application/json")
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	if w.Code != http.StatusOK {
		t.Errorf("expected status 200, got %d: %s", w.Code, w.Body.String())
	}
}

func TestSDLCOrchestratorHandler_Resolve(t *testing.T) {
	exec := &testSDLCExecutor{
		classification: &sdlc.Classification{
			Action:  sdlc.ActionIdle,
			Feature: "auth-flow",
		},
	}
	_, router := setupOrchestratorHandler(exec)

	body, _ := json.Marshal(service.ResolveRequest{Feature: "auth-flow"})
	req := httptest.NewRequest(http.MethodPost, "/projects/test-project/sdlc/resolve", bytes.NewReader(body))
	req.Header.Set("Content-Type", "application/json")
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	if w.Code != http.StatusOK {
		t.Errorf("expected status 200, got %d: %s", w.Code, w.Body.String())
	}
}

func TestSDLCOrchestratorHandler_Resolve_MissingFeature(t *testing.T) {
	exec := &testSDLCExecutor{}
	_, router := setupOrchestratorHandler(exec)

	body, _ := json.Marshal(service.ResolveRequest{})
	req := httptest.NewRequest(http.MethodPost, "/projects/test-project/sdlc/resolve", bytes.NewReader(body))
	req.Header.Set("Content-Type", "application/json")
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	if w.Code != http.StatusBadRequest {
		t.Errorf("expected status 400, got %d: %s", w.Code, w.Body.String())
	}
}

func TestSDLCOrchestratorHandler_Commit(t *testing.T) {
	exec := &testSDLCExecutor{}
	_, router := setupOrchestratorHandler(exec)

	body, _ := json.Marshal(service.CommitRequest{Feature: "auth-flow", Message: "implement auth"})
	req := httptest.NewRequest(http.MethodPost, "/projects/test-project/sdlc/commit", bytes.NewReader(body))
	req.Header.Set("Content-Type", "application/json")
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	// Expected 500 because git committer is nil in test setup
	if w.Code != http.StatusInternalServerError {
		t.Errorf("expected status 500 (no git committer), got %d: %s", w.Code, w.Body.String())
	}
}

func TestSDLCOrchestratorHandler_Commit_MissingMessage(t *testing.T) {
	exec := &testSDLCExecutor{}
	_, router := setupOrchestratorHandler(exec)

	body, _ := json.Marshal(service.CommitRequest{Feature: "auth-flow"})
	req := httptest.NewRequest(http.MethodPost, "/projects/test-project/sdlc/commit", bytes.NewReader(body))
	req.Header.Set("Content-Type", "application/json")
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	if w.Code != http.StatusBadRequest {
		t.Errorf("expected status 400, got %d: %s", w.Code, w.Body.String())
	}
}
