package rosa_test

import (
	"crypto/ed25519"
	"io/fs"
	"log"
	"net/http"
	"net/http/httptest"
	"os"
	"testing"
	"testing/fstest"
	"unique"

	"hakurei.app/check"
	"hakurei.app/fhs"
	"hakurei.app/internal/pkg"
	"hakurei.app/internal/rosa"
	"hakurei.app/message"
)

func TestMirror(t *testing.T) {
	t.Parallel()

	pub, priv, err := ed25519.GenerateKey(nil)
	if err != nil {
		t.Fatal(err)
	}

	base := check.MustAbs(t.TempDir())
	msg := message.New(log.New(os.Stderr, "mirror: ", 0))
	msg.SwapVerbose(testing.Verbose())

	var c *pkg.Cache
	c, err = pkg.Open(t.Context(), msg, base, nil)
	if err != nil {
		t.Fatal(err)
	}
	t.Cleanup(c.Close)

	a := pkg.NewExec(
		"", "",
		nil, 0, false, false,
		fhs.AbsRoot, nil, fhs.AbsRoot, nil,
	)
	id := c.Ident(a)
	ids := pkg.Encode(id.Value())

	var wantChecksum pkg.Checksum
	if err = pkg.SumFS(&wantChecksum, fstest.MapFS{
		".": {Mode: os.ModeDir | 0500},
	}, "."); err != nil {
		t.Fatal(err)
	}
	wantChecksums := pkg.Encode(wantChecksum)

	var mux http.ServeMux
	rosa.NewMirror(msg, fstest.MapFS{
		"identifier/" + ids:         {Mode: fs.ModeSymlink | 0777, Data: []byte("../checksum/" + wantChecksums)},
		"checksum/" + wantChecksums: {Mode: os.ModeDir | 0500},
	}, priv).Register(&mux)
	server := httptest.NewServer(&mux)
	t.Cleanup(server.Close)

	var extern pkg.External
	extern, err = rosa.NewRemote(server.Client(), "http://example.com:80", pub)
	if err != nil {
		t.Fatal(err)
	}
	c.SetExternal(extern)

	var got unique.Handle[pkg.Checksum]
	if _, got, err = c.Cure(a); err != nil {
		t.Fatal(err)
	} else if got.Value() != wantChecksum {
		t.Logf(
			"Cure: checksum = %s, want %s",
			pkg.Encode(got.Value()), pkg.Encode(wantChecksum),
		)
	}
}
