package devagents

import (
	"context"
	"testing"
	"time"
)

// TestAgentStopAndDone verifies that Stop() cancels Run and Done() closes.
// Uses a minimal Agent (no Matrix, no LLM) via direct struct init so the test
// doesn't require network or external dependencies.
func TestAgentStopAndDone(t *testing.T) {
	a := &Agent{
		done: make(chan struct{}),
	}

	// Simulate Run: create the cancel, then immediately block on ctx.
	ctx, cancel := context.WithCancel(context.Background())
	a.cancel = cancel

	started := make(chan struct{})
	go func() {
		close(started)
		// Mimic what Run does: block on ctx, then close done.
		<-ctx.Done()
		close(a.done)
	}()

	<-started

	// Stop must unblock the goroutine above.
	a.Stop()

	select {
	case <-a.Done():
		// ok
	case <-time.After(2 * time.Second):
		t.Fatal("Done() did not close within 2s after Stop()")
	}
}

// TestAgentStopIdempotent verifies that calling Stop() multiple times is safe.
func TestAgentStopIdempotent(t *testing.T) {
	a := &Agent{
		done: make(chan struct{}),
	}
	_, cancel := context.WithCancel(context.Background())
	a.cancel = cancel
	defer cancel()

	// Should not panic when called multiple times.
	a.Stop()
	a.Stop()
	a.Stop()
}

// TestAgentStopNilCancel verifies Stop() is safe when cancel is nil.
func TestAgentStopNilCancel(t *testing.T) {
	a := &Agent{
		done: make(chan struct{}),
	}
	// cancel is nil — must not panic.
	a.Stop()
}
