package api

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

	"gitea.dooplex.hu/admin/felhom-hub/internal/store"
)

// The report ACK advertises the per-customer config_version (v0.26.0). The controller compares it
// against its last-applied version and re-pulls + self-restarts on a change.
func TestReportACK_ConfigVersion(t *testing.T) {
	h, st, _ := newTestHandler(t)

	if err := st.SaveCustomerConfig(&store.CustomerConfig{
		CustomerID: "c", RetrievalPassword: "pw", APIKey: "k", ConfigJSON: "{}",
	}); err != nil {
		t.Fatalf("SaveCustomerConfig: %v", err)
	}

	// First report: ACK carries the baseline version (1).
	rr := do(h, http.MethodPost, "/report", globalKey, `{"customer_id":"c"}`)
	if rr.Code != http.StatusOK {
		t.Fatalf("report status = %d, want 200 (body=%s)", rr.Code, rr.Body.String())
	}
	var ack map[string]interface{}
	if err := json.Unmarshal(rr.Body.Bytes(), &ack); err != nil {
		t.Fatalf("decode ACK: %v", err)
	}
	cv, ok := ack["config_version"]
	if !ok {
		t.Fatalf("ACK missing config_version for a config-managed customer")
	}
	if cv.(float64) != 1 {
		t.Errorf("ACK config_version = %v, want 1 (baseline)", cv)
	}

	// Edit the config → the version bumps → the next ACK carries the new version. This is what makes
	// the box re-pull + restart. RED-PROOF: if SaveCustomerConfig did NOT bump (the bump is dropped),
	// the ACK would still report 1 here and the box would never converge — this assertion fails.
	if err := st.SaveCustomerConfig(&store.CustomerConfig{
		CustomerID: "c", RetrievalPassword: "pw", APIKey: "k", ConfigJSON: `{"git":{"username":"x"}}`,
	}); err != nil {
		t.Fatalf("SaveCustomerConfig (edit): %v", err)
	}
	rr = do(h, http.MethodPost, "/report", globalKey, `{"customer_id":"c"}`)
	if rr.Code != http.StatusOK {
		t.Fatalf("report status = %d, want 200", rr.Code)
	}
	json.Unmarshal(rr.Body.Bytes(), &ack)
	if ack["config_version"].(float64) != 2 {
		t.Errorf("ACK config_version after edit = %v, want 2", ack["config_version"])
	}
}

// A report-only customer (no config row) gets no config_version field — it has nothing to pull, and
// an old controller that ignores the field behaves exactly as before.
func TestReportACK_ConfigVersionOmittedWhenNoConfig(t *testing.T) {
	h, _, _ := newTestHandler(t)

	rr := do(h, http.MethodPost, "/report", globalKey, `{"customer_id":"nobody"}`)
	if rr.Code != http.StatusOK {
		t.Fatalf("report status = %d, want 200", rr.Code)
	}
	var ack map[string]interface{}
	json.Unmarshal(rr.Body.Bytes(), &ack)
	if _, ok := ack["config_version"]; ok {
		t.Errorf("ACK should omit config_version for a report-only (no config) customer; got %v", ack["config_version"])
	}
}
