package main

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"strings"
	"testing"
)

func TestOrasPushInvocationUsesRelativeWorkspacePaths(t *testing.T) {
	dir, args, err := orasPushInvocation("registry.bstein.dev/metis/titan-13:20260331t235724z", "/workspace/build/titan-13.img.xz", "/workspace/build/metadata.json")
	if err != nil {
		t.Fatalf("orasPushInvocation returned error: %v", err)
	}
	if dir != "/workspace/build" {
		t.Fatalf("expected work dir /workspace/build, got %q", dir)
	}
	if len(args) != 4 {
		t.Fatalf("expected 4 args, got %d", len(args))
	}
	if args[0] != "push" {
		t.Fatalf("expected push verb, got %q", args[0])
	}
	if args[1] != "registry.bstein.dev/metis/titan-13:20260331t235724z" {
		t.Fatalf("unexpected ref: %q", args[1])
	}
	if args[2] != "titan-13.img.xz:application/x-raw-disk-image" {
		t.Fatalf("unexpected image arg: %q", args[2])
	}
	if args[3] != "metadata.json:application/json" {
		t.Fatalf("unexpected metadata arg: %q", args[3])
	}
}

func TestWriteStructuredResultFatalOnMarshalError(t *testing.T) {
	oldFatalf := fatalf
	fatalf = func(format string, args ...any) {
		panic(fmt.Sprintf(format, args...))
	}
	defer func() { fatalf = oldFatalf }()
	defer func() {
		if got := recover(); got == nil || !strings.Contains(fmt.Sprint(got), "encode result") {
			t.Fatalf("unexpected panic: %v", got)
		}
	}()
	writeStructuredResult(make(chan int))
}

func TestHumanHostPathMapsMountedTmpBackToHostTmp(t *testing.T) {
	if got := humanHostPath("/host-tmp/metis-flash-test"); got != "/tmp/metis-flash-test" {
		t.Fatalf("expected /tmp/metis-flash-test, got %q", got)
	}
}

func TestNewProgressEmitterWritesStructuredMarker(t *testing.T) {
	origStdout := os.Stdout
	reader, writer, err := os.Pipe()
	if err != nil {
		t.Fatalf("pipe: %v", err)
	}
	os.Stdout = writer
	defer func() {
		os.Stdout = origStdout
	}()

	emitter := newProgressEmitter("flash", 92, 98, "Writing the latest image for titan-12", true)
	emitter(1024, 2048)

	if err := writer.Close(); err != nil {
		t.Fatalf("close writer: %v", err)
	}
	var output bytes.Buffer
	if _, err := io.Copy(&output, reader); err != nil {
		t.Fatalf("read progress output: %v", err)
	}
	got := output.String()
	if !strings.Contains(got, "METIS_PROGRESS ") {
		t.Fatalf("expected structured progress prefix, got %q", got)
	}
	if !strings.Contains(got, `"stage":"flash"`) {
		t.Fatalf("expected flash stage marker, got %q", got)
	}
	if !strings.Contains(got, `"written_bytes":1024`) || !strings.Contains(got, `"total_bytes":2048`) {
		t.Fatalf("expected byte counters in progress marker, got %q", got)
	}
}
