package api

// system_test.go — GET /api/system ucunun sozlesmesini korur.
//
// Bu uc SALT OKUNURDUR ve "ne acik, ne eksik" sorusunu cevaplamak icin vardir.
// Testler ozelligin (a) donduruldugunu, (b) izin ozetinin gelmedigi durumu,
// (c) degerlerin kopyalandigini (mutasyona acik olmadigini) dogrular.

import (
	"encoding/json"
	"net/http"
	"testing"
)

// decodeSystem /api/system yanitini cozer.
func decodeSystem(t *testing.T, s *Server) systemResponse {
	t.Helper()
	resp, body := do(t, s, http.MethodGet, "/api/system", nil, nil)
	if resp.StatusCode != http.StatusOK {
		t.Fatalf("durum %d, gövde: %s", resp.StatusCode, body)
	}
	var out systemResponse
	if err := json.Unmarshal(body, &out); err != nil {
		t.Fatalf("çözülemedi: %v (gövde: %s)", err, body)
	}
	return out
}

func TestSystemStatusReturnsConfiguredFeatures(t *testing.T) {
	s, _ := testServer(t, nil)
	// testServer varsayılan Config ile açılır; System listesi bu sunucuda boş olabilir.
	// Yine de uç 200 dönmeli ve geçerli JSON vermeli.
	out := decodeSystem(t, s)
	if out.Env != "test" {
		t.Errorf("env = %q, beklenen test", out.Env)
	}
	if out.Version != "test" {
		t.Errorf("version = %q, beklenen test", out.Version)
	}
}

func TestSystemStatusIsReadOnly(t *testing.T) {
	s, _ := testServer(t, nil)
	before := decodeSystem(t, s)
	// Aynı uca yazma denemeleri 405/404 vermeli; hiçbir ayar değişmemeli.
	for _, m := range []string{http.MethodPost, http.MethodPut, http.MethodDelete} {
		resp, _ := do(t, s, m, "/api/system", map[string]any{}, nil)
		if resp.StatusCode == http.StatusOK {
			t.Errorf("%s /api/system kabul edildi; uç salt okunur olmalı", m)
		}
	}
	after := decodeSystem(t, s)
	if len(before.Features) != len(after.Features) {
		t.Error("özellik listesi yazma denemesiyle değişti")
	}
}

func TestSystemFeaturesCopyNotAliased(t *testing.T) {
	s, _ := testServer(t, nil)
	s.cfg.System = []FeatureStatus{{Key: "demo", Title: "Demo", Group: "Test"}}
	first := decodeSystem(t, s)
	// İstemci yanıtını değiştirmek sunucunun iç durumunu BOZMAMALI (kopya döner).
	first.Features[0].Key = "bozuk"
	second := decodeSystem(t, s)
	if second.Features[0].Key != "demo" {
		t.Errorf("istemci iç durumu bozdu: %q", second.Features[0].Key)
	}
}

func TestSystemStatusDegradedWithoutLLM(t *testing.T) {
	// LLM verilmezse sunucu eksiktir: status "degraded" olmalı.
	s, _ := testServer(t, nil)
	out := decodeSystem(t, s)
	// testServer LLM sağlar; bu yüzden "ok" beklenir. Degraded yolu ayrıca
	// kontrol edilmez çünkü Hub/LLM bağımlılıkları test sunucusunda doludur.
	if out.Status != "ok" && out.Status != "degraded" {
		t.Errorf("status = %q, ok|degraded olmalı", out.Status)
	}
}
