package rest_test

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

	"github.com/pingcap/agent-git-service/internal/service"
	"github.com/pingcap/agent-git-service/internal/testharness"
)

func TestWikiPublicationHTTPViewsAgreeAfterInterruptedWrite(t *testing.T) {
	h := testharness.New(t)
	compatSeedRepo(t, h, "publication")
	ctx := h.Tenant.Context()
	full := "testuser/publication"
	base := "/api/ext/v1/repos/" + full + "/wiki"
	old, err := h.Svc.PutWikiPage(ctx, full, "home", "Calls: 1366", "seed", "")
	if err != nil {
		t.Fatal(err)
	}
	if _, err := h.Svc.ReconcileWikiV2(ctx, full); err != nil {
		t.Fatal(err)
	}
	before := h.DoREST(t, http.MethodGet, base+"/catalog?include=tree", nil)
	assertStatusCode(t, before, http.StatusOK)
	service.SetTestWikiPreparedPublishFailureForTest(h.Svc, func(string, string) error { return errors.New("interrupted publication") })
	defer service.SetTestWikiPreparedPublishFailureForTest(h.Svc, nil)
	failed := h.DoRESTJSON(t, http.MethodPut, base+"/pages/home", map[string]any{"body": "Calls: 1545", "message": "update", "sha": old.SHA})
	assertStatusCode(t, failed, http.StatusInternalServerError)
	service.SetTestWikiPreparedPublishFailureForTest(h.Svc, nil)
	pageResp := h.DoREST(t, http.MethodGet, base+"/pages/home", nil)
	assertStatusCode(t, pageResp, http.StatusOK)
	page := testharness.DecodeJSON(t, pageResp)
	if page["body"] != "Calls: 1545" || page["sha"] == old.SHA {
		t.Fatalf("stale page: %+v", page)
	}
	batchResp := h.DoRESTJSON(t, http.MethodPost, base+"/pages/batch", map[string]any{"slugs": []string{"home", "missing"}})
	assertStatusCode(t, batchResp, http.StatusOK)
	batch := testharness.DecodeJSON(t, batchResp)
	items := batch["items"].([]any)
	if len(items) != 1 || items[0].(map[string]any)["sha"] != page["sha"] || items[0].(map[string]any)["body"] != page["body"] {
		t.Fatalf("stale batch: %+v", batch)
	}
	catalogResp := h.DoREST(t, http.MethodGet, base+"/catalog?include=pages,tree&recursive=true", nil)
	assertStatusCode(t, catalogResp, http.StatusOK)
	catalog := testharness.DecodeJSON(t, catalogResp)
	for _, key := range []string{"pages", "tree"} {
		rows := catalog[key].([]any)
		if len(rows) != 1 || rows[0].(map[string]any)["sha"] != page["sha"] {
			t.Fatalf("inconsistent %s: %+v", key, rows)
		}
	}
	conditional := httptest.NewRequest(http.MethodGet, base+"/catalog?include=tree", nil)
	conditional.Header.Set("Authorization", "token "+h.Token)
	conditional.Header.Set("If-None-Match", before.Header().Get("ETag"))
	after := httptest.NewRecorder()
	h.Mux.ServeHTTP(after, conditional)
	assertStatusCode(t, after, http.StatusOK)
	if after.Header().Get("ETag") == before.Header().Get("ETag") {
		t.Fatal("stale navigation ETag")
	}
}
