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 TestAppointmentCreate_NoTenant(t *testing.T) {
	h := &AppointmentHandler{}
	r := httptest.NewRequest("POST", "/api/appointments", bytes.NewBufferString(`{}`))
	w := httptest.NewRecorder()

	h.Create(w, r)

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

func TestAppointmentCreate_MissingTitle(t *testing.T) {
	h := &AppointmentHandler{}
	body := `{"start_at":"2026-04-01T10:00:00Z"}`
	r := httptest.NewRequest("POST", "/api/appointments", 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"] != "title is required" {
		t.Errorf("unexpected error: %s", resp["error"])
	}
}

func TestAppointmentCreate_MissingStartAt(t *testing.T) {
	h := &AppointmentHandler{}
	body := `{"title":"Test Appointment"}`
	r := httptest.NewRequest("POST", "/api/appointments", 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"] != "start_at is required" {
		t.Errorf("unexpected error: %s", resp["error"])
	}
}

func TestAppointmentCreate_InvalidJSON(t *testing.T) {
	h := &AppointmentHandler{}
	r := httptest.NewRequest("POST", "/api/appointments", bytes.NewBufferString(`{broken`))
	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 TestAppointmentList_NoTenant(t *testing.T) {
	h := &AppointmentHandler{}
	r := httptest.NewRequest("GET", "/api/appointments", nil)
	w := httptest.NewRecorder()

	h.List(w, r)

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

func TestAppointmentUpdate_NoTenant(t *testing.T) {
	h := &AppointmentHandler{}
	r := httptest.NewRequest("PUT", "/api/appointments/"+uuid.New().String(), bytes.NewBufferString(`{}`))
	r.SetPathValue("id", uuid.New().String())
	w := httptest.NewRecorder()

	h.Update(w, r)

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

func TestAppointmentUpdate_InvalidID(t *testing.T) {
	h := &AppointmentHandler{}
	r := httptest.NewRequest("PUT", "/api/appointments/not-uuid", bytes.NewBufferString(`{}`))
	r.SetPathValue("id", "not-uuid")
	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 TestAppointmentDelete_NoTenant(t *testing.T) {
	h := &AppointmentHandler{}
	r := httptest.NewRequest("DELETE", "/api/appointments/"+uuid.New().String(), nil)
	r.SetPathValue("id", uuid.New().String())
	w := httptest.NewRecorder()

	h.Delete(w, r)

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

func TestAppointmentDelete_InvalidID(t *testing.T) {
	h := &AppointmentHandler{}
	r := httptest.NewRequest("DELETE", "/api/appointments/bad", nil)
	r.SetPathValue("id", "bad")
	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)
	}
}

func TestAppointmentList_InvalidCaseID(t *testing.T) {
	h := &AppointmentHandler{}
	r := httptest.NewRequest("GET", "/api/appointments?case_id=bad", nil)
	ctx := auth.ContextWithTenantID(
		auth.ContextWithUserID(r.Context(), uuid.New()),
		uuid.New(),
	)
	r = r.WithContext(ctx)
	w := httptest.NewRecorder()

	h.List(w, r)

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

func TestAppointmentList_InvalidStartFrom(t *testing.T) {
	h := &AppointmentHandler{}
	r := httptest.NewRequest("GET", "/api/appointments?start_from=not-a-date", nil)
	ctx := auth.ContextWithTenantID(
		auth.ContextWithUserID(r.Context(), uuid.New()),
		uuid.New(),
	)
	r = r.WithContext(ctx)
	w := httptest.NewRecorder()

	h.List(w, r)

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