package manifest_test

import (
	"testing"
	"time"

	"github.com/jfraeys/fetch_ml/internal/manifest"
)

func TestRunManifestWriteLoadAndMarkFinished(t *testing.T) {
	dir := t.TempDir()
	created := time.Date(2025, 12, 16, 0, 0, 0, 0, time.UTC)
	m := manifest.NewRunManifest("run-test-20251216-000000-12345678", "12345678", "job", created)
	m.CommitID = "deadbeef"
	m.PodmanImage = "python:3.11"
	m.AddAnnotation(created.Add(1*time.Second), "alice", "initial hypothesis")
	m.AddAnnotation(created.Add(1*time.Second), "", "")

	hyp := "  bigger batch improves throughput  "
	tags := []string{" ablation ", "", "batch-size"}
	m.ApplyNarrativePatch(manifest.NarrativePatch{
		Hypothesis: &hyp,
		Tags:       &tags,
	})

	start := created.Add(2 * time.Second)
	m.MarkStarted(start)

	if err := m.WriteToDir(dir); err != nil {
		t.Fatalf("WriteToDir failed: %v", err)
	}

	loaded, err := manifest.LoadFromDir(dir)
	if err != nil {
		t.Fatalf("LoadFromDir failed: %v", err)
	}
	if loaded.RunID != m.RunID {
		t.Fatalf("run id mismatch: got %q want %q", loaded.RunID, m.RunID)
	}
	if loaded.StartedAt.IsZero() {
		t.Fatalf("expected started_at to be set")
	}
	if len(loaded.Annotations) != 1 {
		t.Fatalf("expected 1 annotation, got %d", len(loaded.Annotations))
	}
	if loaded.Narrative == nil {
		t.Fatalf("expected narrative to be set")
	}
	if loaded.Narrative.Hypothesis != "bigger batch improves throughput" {
		t.Fatalf("unexpected hypothesis: %q", loaded.Narrative.Hypothesis)
	}
	if len(loaded.Narrative.Tags) != 2 {
		t.Fatalf("expected 2 tags, got %d", len(loaded.Narrative.Tags))
	}
	if loaded.Narrative.Tags[0] != "ablation" || loaded.Narrative.Tags[1] != "batch-size" {
		t.Fatalf("unexpected tags: %#v", loaded.Narrative.Tags)
	}
	if loaded.Annotations[0].Author != "alice" {
		t.Fatalf("expected annotation author %q, got %q", "alice", loaded.Annotations[0].Author)
	}
	if loaded.Annotations[0].Timestamp.IsZero() {
		t.Fatalf("expected annotation timestamp to be set")
	}
	if loaded.Annotations[0].Note != "initial hypothesis" {
		t.Fatalf("expected annotation note %q, got %q", "initial hypothesis", loaded.Annotations[0].Note)
	}

	end := start.Add(5 * time.Second)
	exit := 0
	loaded.MarkFinished(end, &exit, nil)
	if loaded.TotalDurationMS == 0 {
		t.Fatalf("expected total duration to be set")
	}
	if err := loaded.WriteToDir(dir); err != nil {
		t.Fatalf("final WriteToDir failed: %v", err)
	}

	loaded2, err := manifest.LoadFromDir(dir)
	if err != nil {
		t.Fatalf("LoadFromDir (2) failed: %v", err)
	}
	if loaded2.ExitCode == nil || *loaded2.ExitCode != 0 {
		t.Fatalf("expected exit_code 0, got %#v", loaded2.ExitCode)
	}
	if loaded2.TotalDurationMS <= 0 {
		t.Fatalf("expected total duration > 0")
	}
}

func TestRunManifestApplyNarrativePatchPartialUpdate(t *testing.T) {
	created := time.Date(2026, 1, 7, 0, 0, 0, 0, time.UTC)
	m := manifest.NewRunManifest("run-test-20260107-000000-12345678", "12345678", "job", created)

	h1 := "hyp1"
	m.ApplyNarrativePatch(manifest.NarrativePatch{Hypothesis: &h1})

	ctx := "ctx"
	m.ApplyNarrativePatch(manifest.NarrativePatch{Context: &ctx})

	if m.Narrative == nil {
		t.Fatalf("expected narrative to be non-nil")
	}
	if m.Narrative.Hypothesis != "hyp1" {
		t.Fatalf("expected hypothesis to remain set")
	}
	if m.Narrative.Context != "ctx" {
		t.Fatalf("expected context to be set")
	}
}
