package webrtc

import (
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/labstack/echo/v4"

	"github.com/datarhei/core/v16/config"
)

func newTestSubsystem(t *testing.T) *Subsystem {
	t.Helper()
	s, err := New(config.DataWebRTC{Enable: true}, nil)
	if err != nil {
		t.Fatalf("New: %v", err)
	}
	return s
}

// TestHandler_Subscribe_404WhenStreamMissing verifies the WHEP POST
// returns 404 when no process has registered a stream for that id.
func TestHandler_Subscribe_404WhenStreamMissing(t *testing.T) {
	h := NewHandler(newTestSubsystem(t), 0)

	e := echo.New()
	req := httptest.NewRequest(http.MethodPost, "/whep/ghost", strings.NewReader("v=0\r\n"))
	rec := httptest.NewRecorder()
	c := e.NewContext(req, rec)
	c.SetParamNames("id")
	c.SetParamValues("ghost")

	if err := h.Subscribe(c); err != nil {
		t.Fatalf("Subscribe returned error: %v", err)
	}

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

// TestHandler_Subscribe_400OnEmptyBody verifies invalid SDP offers
// short-circuit before any peer is created. Requires a registered
// stream so lookup doesn't 404 first.
func TestHandler_Subscribe_400OnEmptyBody(t *testing.T) {
	sub := newTestSubsystem(t)
	// Register a dummy stream so the handler reaches body validation.
	sub.mu.Lock()
	sub.streams["probe"] = &processStream{id: "probe"} // video/audio nil is fine here — we never get past body parse
	sub.mu.Unlock()

	h := NewHandler(sub, 0)

	e := echo.New()
	req := httptest.NewRequest(http.MethodPost, "/whep/probe", strings.NewReader(""))
	rec := httptest.NewRecorder()
	c := e.NewContext(req, rec)
	c.SetParamNames("id")
	c.SetParamValues("probe")

	if err := h.Subscribe(c); err != nil {
		t.Fatalf("Subscribe returned error: %v", err)
	}
	if rec.Code != http.StatusBadRequest {
		t.Fatalf("expected 400, got %d: %s", rec.Code, rec.Body.String())
	}
}

// TestHandler_Unsubscribe_204WhenUnknown verifies a DELETE with an
// unknown resource id returns 204 (idempotent), per the WHEP spec
// and the M2/M3 design's error matrix. Pre-M3 this returned 404; the
// updated semantics let clients re-issue DELETE without erroring.
func TestHandler_Unsubscribe_204WhenUnknown(t *testing.T) {
	h := NewHandler(newTestSubsystem(t), 0)

	e := echo.New()
	req := httptest.NewRequest(http.MethodDelete, "/whep/id/unknown", nil)
	rec := httptest.NewRecorder()
	c := e.NewContext(req, rec)
	c.SetParamNames("id", "resource")
	c.SetParamValues("id", "unknown")

	if err := h.Unsubscribe(c); err != nil {
		t.Fatalf("Unsubscribe returned error: %v", err)
	}
	if rec.Code != http.StatusNoContent {
		t.Fatalf("expected 204, got %d", rec.Code)
	}
}
