package httpapi

import (
	"bytes"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
	"time"
)

// TestPlayerStatusLifecycle covers the full lifecycle of a screen status entry:
// ingest → list → HTML detail → JSON detail → delete → verify gone.
func TestPlayerStatusLifecycle(t *testing.T) {
	store := newInMemoryPlayerStatusStore()
	store.now = func() time.Time {
		return time.Date(2026, 3, 22, 16, 10, 0, 0, time.UTC)
	}
	router := NewRouter(RouterDeps{StatusStore: store})

	// 1. POST /api/v1/player/status – ingest a status report
	body := `{
		"screen_id": "lifecycle-screen",
		"ts": "2026-03-22T16:09:30Z",
		"status": "running",
		"server_connectivity": "online",
		"server_url": "http://127.0.0.1:8080",
		"mqtt_broker": "tcp://127.0.0.1:1883",
		"heartbeat_every_seconds": 30,
		"started_at": "2026-03-22T16:00:00Z",
		"last_heartbeat_at": "2026-03-22T16:09:30Z"
	}`
	req := httptest.NewRequest(http.MethodPost, "/api/v1/player/status", bytes.NewBufferString(body))
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)
	if got, want := w.Code, http.StatusOK; got != want {
		t.Fatalf("POST status: got %d, want %d – body: %s", got, want, w.Body.String())
	}

	// 2. GET /api/v1/screens/status – appears in list with derived_state=online
	req = httptest.NewRequest(http.MethodGet, "/api/v1/screens/status", nil)
	w = httptest.NewRecorder()
	router.ServeHTTP(w, req)
	if got, want := w.Code, http.StatusOK; got != want {
		t.Fatalf("GET list: got %d, want %d", got, want)
	}
	var list struct {
		Summary struct{ Total int }       `json:"summary"`
		Screens []playerStatusRecord `json:"screens"`
	}
	if err := json.Unmarshal(w.Body.Bytes(), &list); err != nil {
		t.Fatalf("GET list Unmarshal: %v", err)
	}
	if got, want := list.Summary.Total, 1; got != want {
		t.Fatalf("summary.total = %d, want %d", got, want)
	}
	if got, want := list.Screens[0].ScreenID, "lifecycle-screen"; got != want {
		t.Fatalf("Screens[0].ScreenID = %q, want %q", got, want)
	}
	if got, want := list.Screens[0].DerivedState, "online"; got != want {
		t.Fatalf("Screens[0].DerivedState = %q, want %q", got, want)
	}

	// 3. GET /status/lifecycle-screen – HTML detail page contains key fields
	req = httptest.NewRequest(http.MethodGet, "/status/lifecycle-screen", nil)
	w = httptest.NewRecorder()
	router.ServeHTTP(w, req)
	if got, want := w.Code, http.StatusOK; got != want {
		t.Fatalf("GET HTML detail: got %d, want %d", got, want)
	}
	if ct := w.Header().Get("Content-Type"); !strings.Contains(ct, "text/html") {
		t.Fatalf("Content-Type = %q, want text/html", ct)
	}
	htmlBody := w.Body.String()
	for _, want := range []string{"lifecycle-screen", "online", "running"} {
		if !strings.Contains(htmlBody, want) {
			t.Fatalf("HTML detail page missing %q", want)
		}
	}

	// 4. GET /api/v1/screens/lifecycle-screen/status – JSON detail
	req = httptest.NewRequest(http.MethodGet, "/api/v1/screens/lifecycle-screen/status", nil)
	w = httptest.NewRecorder()
	router.ServeHTTP(w, req)
	if got, want := w.Code, http.StatusOK; got != want {
		t.Fatalf("GET JSON detail: got %d, want %d", got, want)
	}
	var detail playerStatusRecord
	if err := json.Unmarshal(w.Body.Bytes(), &detail); err != nil {
		t.Fatalf("GET JSON detail Unmarshal: %v", err)
	}
	if got, want := detail.ScreenID, "lifecycle-screen"; got != want {
		t.Fatalf("detail.ScreenID = %q, want %q", got, want)
	}
	if got, want := detail.ServerURL, "http://127.0.0.1:8080"; got != want {
		t.Fatalf("detail.ServerURL = %q, want %q", got, want)
	}

	// 5. DELETE /api/v1/screens/lifecycle-screen/status – remove the record
	req = httptest.NewRequest(http.MethodDelete, "/api/v1/screens/lifecycle-screen/status", nil)
	w = httptest.NewRecorder()
	router.ServeHTTP(w, req)
	if got, want := w.Code, http.StatusOK; got != want {
		t.Fatalf("DELETE: got %d, want %d – body: %s", got, want, w.Body.String())
	}

	// 6. GET /api/v1/screens/lifecycle-screen/status – must be 404 now
	req = httptest.NewRequest(http.MethodGet, "/api/v1/screens/lifecycle-screen/status", nil)
	w = httptest.NewRecorder()
	router.ServeHTTP(w, req)
	if got, want := w.Code, http.StatusNotFound; got != want {
		t.Fatalf("GET after delete: got %d, want %d", got, want)
	}

	// 7. GET /api/v1/screens/status – list must be empty again
	req = httptest.NewRequest(http.MethodGet, "/api/v1/screens/status", nil)
	w = httptest.NewRecorder()
	router.ServeHTTP(w, req)
	if err := json.Unmarshal(w.Body.Bytes(), &list); err != nil {
		t.Fatalf("GET list after delete Unmarshal: %v", err)
	}
	if got, want := list.Summary.Total, 0; got != want {
		t.Fatalf("summary.total after delete = %d, want %d", got, want)
	}
}
