package web

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

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

// R-50b(a) — the wrapper-sha field must render INSIDE the artifact form, and the form's grid must
// stay structurally intact.
//
// This test exists because the first attempt at this field shipped broken: it wrapped the row in a
// <div> and, since the <form> ITSELF is the CSS grid (`display: grid`, no inner container), the
// stray `</div>` closed the surrounding CARD from inside the form and the newly-opened <div> was
// never closed — it swallowed the submit button and ran to </form>. The page rendered with the row
// escaped outside the card and the Save button inline. Nothing failed: there was no render
// assertion on this form at all.
func TestConfigurationArtifactsForm_Structure(t *testing.T) {
	s, _ := newTestServer(t)
	data := map[string]interface{}{
		"CSRFToken":     "tok",
		"CSRFField":     s.csrfField(httptest.NewRequest("GET", "/", nil)),
		"AssetCount":    0,
		"AssetLastSync": "",
		"GlobalFloor":   "0.86.0",
		"Artifacts": store.ArtifactManifest{
			AgentVersion:  "0.91.2",
			GoldenVersion: "0.153.0",
			MinAgent:      "0.91.2",
			WrapperSHA256: "104db0a4401f65bbc476e82bfb1796433bcb36f8f8cce69efb3bb5c40fcb16b3",
		},
	}
	var buf bytes.Buffer
	if err := s.templates.ExecuteTemplate(&buf, "configuration.html", data); err != nil {
		t.Fatalf("render: %v", err)
	}
	body := buf.String()

	// 1. The field renders, carries its stored value, and is reachable for the operator.
	if !strings.Contains(body, `name="wrapper_sha256"`) {
		t.Fatal("the wrapper sha256 input is missing from the Configuration page")
	}
	if !strings.Contains(body, "104db0a4401f65bbc476e82bfb1796433bcb36f8f8cce69efb3bb5c40fcb16b3") {
		t.Error("the stored wrapper sha256 is not rendered into the field — the operator cannot see what is vouched")
	}

	// 2. THE STRUCTURAL ASSERTION. It must sit inside the artifacts <form>, or it is never submitted.
	form := artifactsForm(t, body)
	if !strings.Contains(form, `name="wrapper_sha256"`) {
		t.Error("the wrapper sha256 input is OUTSIDE the artifacts form — it would never be submitted")
	}
	if !strings.Contains(form, "Save artifact manifest") {
		t.Error("the submit button escaped the artifacts form")
	}

	// 3. The form is the grid: any <div> inside it breaks the column layout and, unbalanced, breaks
	//    the surrounding card too. That is exactly how this shipped wrong the first time.
	if n := strings.Count(form, "<div"); n != 0 {
		t.Errorf("the artifacts form contains %d <div> element(s) — the form IS the CSS grid; "+
			"a nested div breaks the column layout", n)
	}
	if o, c := strings.Count(form, "<div"), strings.Count(form, "</div>"); o != c {
		t.Errorf("unbalanced div tags inside the artifacts form: %d open, %d close", o, c)
	}

	// 4. Whole-page div balance — an unclosed div here corrupts every section BELOW it (the login
	//    password card and the assets card both render after this form).
	if o, c := strings.Count(body, "<div"), strings.Count(body, "</div>"); o != c {
		t.Errorf("configuration.html has unbalanced divs: %d open, %d close — sections after the "+
			"artifact form will render inside the wrong container", o, c)
	}

	// 5. The sections that follow must still be present and not swallowed.
	for _, want := range []string{"Login password", "Change password", "Assets", "Refresh Assets from Image"} {
		if !strings.Contains(body, want) {
			t.Errorf("section %q missing — likely swallowed by an unclosed element above it", want)
		}
	}
}

var artifactsFormRe = regexp.MustCompile(`(?s)<form[^>]*action="/configuration/artifacts"[^>]*>(.*?)</form>`)

func artifactsForm(t *testing.T, body string) string {
	t.Helper()
	m := artifactsFormRe.FindStringSubmatch(body)
	if m == nil {
		t.Fatal("could not locate the artifacts form")
	}
	return m[1]
}

// An empty stored value must render an empty field (blank = not vouched), not the string "<no value>"
// or a zero — the operator reads this field to decide whether anything is vouched at all.
func TestConfigurationArtifactsForm_EmptyWrapperSHA(t *testing.T) {
	s, _ := newTestServer(t)
	var buf bytes.Buffer
	err := s.templates.ExecuteTemplate(&buf, "configuration.html", map[string]interface{}{
		"CSRFToken": "tok", "CSRFField": s.csrfField(httptest.NewRequest("GET", "/", nil)),
		"AssetCount": 0, "AssetLastSync": "", "GlobalFloor": "",
		"Artifacts": store.ArtifactManifest{},
	})
	if err != nil {
		t.Fatalf("render: %v", err)
	}
	form := artifactsForm(t, buf.String())
	if !strings.Contains(form, `name="wrapper_sha256" value=""`) {
		t.Errorf("an unvouched wrapper must render an empty value; got:\n%s", form)
	}
}
