package handlers

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

	"github.com/google/uuid"

	"mgit.msbls.de/m/KanzlAI-mGMT/internal/auth"
)

func TestCaseCreate_NoAuth(t *testing.T) {
	h := &CaseHandler{}
	r := httptest.NewRequest("POST", "/api/cases", bytes.NewBufferString(`{}`))
	w := httptest.NewRecorder()

	h.Create(w, r)

	if w.Code != http.StatusForbidden {
		t.Errorf("expected 403, got %d", w.Code)
	}
}

func TestCaseCreate_MissingFields(t *testing.T) {
	h := &CaseHandler{}
	body := `{"case_number":"","title":""}`
	r := httptest.NewRequest("POST", "/api/cases", bytes.NewBufferString(body))
	ctx := auth.ContextWithTenantID(
		auth.ContextWithUserID(r.Context(), uuid.New()),
		uuid.New(),
	)
	r = r.WithContext(ctx)
	w := httptest.NewRecorder()

	h.Create(w, r)

	if w.Code != http.StatusBadRequest {
		t.Errorf("expected 400, got %d", w.Code)
	}
	var resp map[string]string
	json.NewDecoder(w.Body).Decode(&resp)
	if resp["error"] != "case_number and title are required" {
		t.Errorf("unexpected error: %s", resp["error"])
	}
}

func TestCaseCreate_InvalidJSON(t *testing.T) {
	h := &CaseHandler{}
	r := httptest.NewRequest("POST", "/api/cases", bytes.NewBufferString(`not-json`))
	ctx := auth.ContextWithTenantID(
		auth.ContextWithUserID(r.Context(), uuid.New()),
		uuid.New(),
	)
	r = r.WithContext(ctx)
	w := httptest.NewRecorder()

	h.Create(w, r)

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

func TestCaseGet_InvalidID(t *testing.T) {
	h := &CaseHandler{}
	r := httptest.NewRequest("GET", "/api/cases/not-a-uuid", nil)
	r.SetPathValue("id", "not-a-uuid")
	ctx := auth.ContextWithTenantID(
		auth.ContextWithUserID(r.Context(), uuid.New()),
		uuid.New(),
	)
	r = r.WithContext(ctx)
	w := httptest.NewRecorder()

	h.Get(w, r)

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

func TestCaseGet_NoTenant(t *testing.T) {
	h := &CaseHandler{}
	r := httptest.NewRequest("GET", "/api/cases/"+uuid.New().String(), nil)
	r.SetPathValue("id", uuid.New().String())
	w := httptest.NewRecorder()

	h.Get(w, r)

	if w.Code != http.StatusForbidden {
		t.Errorf("expected 403, got %d", w.Code)
	}
}

func TestCaseList_NoTenant(t *testing.T) {
	h := &CaseHandler{}
	r := httptest.NewRequest("GET", "/api/cases", nil)
	w := httptest.NewRecorder()

	h.List(w, r)

	if w.Code != http.StatusForbidden {
		t.Errorf("expected 403, got %d", w.Code)
	}
}

func TestCaseUpdate_InvalidID(t *testing.T) {
	h := &CaseHandler{}
	body := `{"title":"Updated"}`
	r := httptest.NewRequest("PUT", "/api/cases/bad-id", bytes.NewBufferString(body))
	r.SetPathValue("id", "bad-id")
	ctx := auth.ContextWithTenantID(
		auth.ContextWithUserID(r.Context(), uuid.New()),
		uuid.New(),
	)
	r = r.WithContext(ctx)
	w := httptest.NewRecorder()

	h.Update(w, r)

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

func TestCaseUpdate_InvalidJSON(t *testing.T) {
	h := &CaseHandler{}
	caseID := uuid.New().String()
	r := httptest.NewRequest("PUT", "/api/cases/"+caseID, bytes.NewBufferString(`{bad`))
	r.SetPathValue("id", caseID)
	ctx := auth.ContextWithTenantID(
		auth.ContextWithUserID(r.Context(), uuid.New()),
		uuid.New(),
	)
	r = r.WithContext(ctx)
	w := httptest.NewRecorder()

	h.Update(w, r)

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

func TestCaseDelete_NoTenant(t *testing.T) {
	h := &CaseHandler{}
	r := httptest.NewRequest("DELETE", "/api/cases/"+uuid.New().String(), nil)
	r.SetPathValue("id", uuid.New().String())
	w := httptest.NewRecorder()

	h.Delete(w, r)

	if w.Code != http.StatusForbidden {
		t.Errorf("expected 403, got %d", w.Code)
	}
}

func TestCaseDelete_InvalidID(t *testing.T) {
	h := &CaseHandler{}
	r := httptest.NewRequest("DELETE", "/api/cases/bad-id", nil)
	r.SetPathValue("id", "bad-id")
	ctx := auth.ContextWithTenantID(
		auth.ContextWithUserID(r.Context(), uuid.New()),
		uuid.New(),
	)
	r = r.WithContext(ctx)
	w := httptest.NewRecorder()

	h.Delete(w, r)

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