package web

import (
	"html/template"
	"net/url"
	"strings"
	"testing"

	"gitea.dooplex.hu/admin/felhom-controller/internal/infra"
)

// The deep-link template, pinned against the shipped FileBrowser Quantum router (SPIKE P2).
func TestFileBrowserLink_Template(t *testing.T) {
	const dom = "demo-felhom.eu"
	for _, tc := range []struct{ name, source, rel, want string }{
		{"ascii source, one segment", "hdd_1", "media/movies",
			"https://files.demo-felhom.eu/files/hdd_1/media/movies"},
		{"accented source (the import label)", infra.FileBrowserImportLabel, "paperless",
			"https://files.demo-felhom.eu/files/Beolvas%C3%A1s/paperless"},
		{"source root, empty relpath", infra.FileBrowserImportLabel, "",
			"https://files.demo-felhom.eu/files/Beolvas%C3%A1s"},
		{"leading/trailing slashes are ignored", "hdd_1", "/media/books/",
			"https://files.demo-felhom.eu/files/hdd_1/media/books"},
		{"accented path segment", "hdd_1", "media/könyvek",
			"https://files.demo-felhom.eu/files/hdd_1/media/k%C3%B6nyvek"},
	} {
		if got := fileBrowserLink(dom, tc.source, tc.rel); got != tc.want {
			t.Errorf("%s:\n got  %q\n want %q", tc.name, got, tc.want)
		}
	}
}

// THE trap, measured in SPIKE P2. QueryEscape turns a space into "+", which in a path segment is a
// literal plus and lands the customer on a folder that does not exist. This test fails if anyone
// swaps the escaper.
func TestFileBrowserLink_UsesPathEscapeNotQueryEscape(t *testing.T) {
	const spaced = "Média & könyvtár"
	got := fileBrowserLink("x.eu", spaced, "a b")

	if strings.Contains(got, "+") {
		t.Errorf("link contains '+' — QueryEscape was used somewhere; a '+' in a path segment is a literal plus, not a space: %q", got)
	}
	if want := url.PathEscape(spaced); !strings.Contains(got, want) {
		t.Errorf("source not PathEscape'd: got %q, want it to contain %q", got, want)
	}
	// Guard the exact divergence the spike measured, so the two escapers can never be confused here.
	if url.PathEscape(spaced) == url.QueryEscape(spaced) {
		t.Fatal("fixture no longer distinguishes the two escapers — pick a name where they differ")
	}
	if strings.Contains(got, url.QueryEscape(spaced)) {
		t.Errorf("link used QueryEscape: %q", got)
	}
}

// The link is embedded in HTML. Percent-encoding and attribute-escaping must COMPOSE: PathEscape
// leaves "&" bare, html/template turns it into "&amp;", and the browser decodes it back to "&".
// Anything that double-encodes (a hand-rolled HTML escape before the template) breaks the path.
func TestFileBrowserLink_ComposesWithHTMLEscaping(t *testing.T) {
	link := fileBrowserLink("x.eu", "Média & könyvtár", "docs")
	var sb strings.Builder
	tmpl := template.Must(template.New("a").Parse(`<a href="{{.}}">x</a>`))
	if err := tmpl.Execute(&sb, link); err != nil {
		t.Fatal(err)
	}
	out := sb.String()
	if !strings.Contains(out, "&amp;") {
		t.Errorf("html/template should escape the bare & in the href: %q", out)
	}
	// It must NOT have been percent-encoded a second time (%2526 etc. would be double-encoding).
	if strings.Contains(out, "%25") {
		t.Errorf("double percent-encoding detected — do not pre-escape before the template: %q", out)
	}
	// And no raw quote/angle escaped into the attribute.
	if strings.Contains(out, `href=""`) {
		t.Errorf("html/template refused the URL (would render an empty href): %q", out)
	}
}

// importFolderLink targets the CANONICAL source, so a drop-zone link is identical regardless of
// which drive the app itself sits on.
func TestImportFolderLink_IsCanonical(t *testing.T) {
	a := importFolderLink("demo-felhom.eu", "paperless")
	b := importFolderLink("demo-felhom.eu", "calibre")
	for _, l := range []string{a, b} {
		if !strings.Contains(l, "/files/"+url.PathEscape(infra.FileBrowserImportLabel)+"/") {
			t.Errorf("import link must go through the canonical source: %q", l)
		}
		if strings.Contains(l, "hdd_1") || strings.Contains(l, "felhom-drives") {
			t.Errorf("import link must never name a data drive: %q", l)
		}
	}
	if a == b {
		t.Error("different apps must get different folders")
	}
}
