package infra

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

func TestPTYCaptureStream(t *testing.T) {

	t.Run("snapshots crecientes con pausas", func(t *testing.T) {
		if testing.Short() {
			t.Skip("skip en modo corto: timing sensible")
		}
		ctx := context.Background()
		// bash -lc imprime A, pausa 0.3s, B, pausa 0.3s, C, pausa 0.3s.
		// Con snapshotInterval 100ms e idle 400ms debería recibir varios snapshots
		// y el último debe contener A, B y C.
		ch, err := PTYCaptureStream(
			ctx,
			"bash", []string{"-lc", "printf A; sleep 0.3; printf B; sleep 0.3; printf C; sleep 0.3"},
			50*time.Millisecond,  // warmup
			nil,                   // inputs
			0,                     // stepDelay
			100*time.Millisecond,  // snapshotInterval
			400*time.Millisecond,  // idle
			5*time.Second,         // maxDur
		)
		if err != nil {
			t.Fatalf("error inesperado al arrancar: %v", err)
		}

		var snapshots []string
		for s := range ch {
			snapshots = append(snapshots, s)
		}

		if len(snapshots) < 2 {
			t.Errorf("se esperaban >=2 snapshots, got %d", len(snapshots))
		}

		// Snapshots deben ser acumulativos (monótonos en longitud).
		for i := 1; i < len(snapshots); i++ {
			if len(snapshots[i]) < len(snapshots[i-1]) {
				t.Errorf("snapshot[%d] len=%d < snapshot[%d] len=%d — no acumulativo",
					i, len(snapshots[i]), i-1, len(snapshots[i-1]))
			}
		}

		// El último snapshot debe contener A, B y C.
		last := snapshots[len(snapshots)-1]
		for _, want := range []string{"A", "B", "C"} {
			if !strings.Contains(last, want) {
				t.Errorf("último snapshot no contiene %q: %q", want, last)
			}
		}
	})

	t.Run("snapshot final siempre presente", func(t *testing.T) {
		if testing.Short() {
			t.Skip("skip en modo corto")
		}
		ctx := context.Background()
		// Output instantáneo; con idle 300ms el canal cierra rápido.
		ch, err := PTYCaptureStream(
			ctx,
			"bash", []string{"-lc", "printf HOLA"},
			50*time.Millisecond,
			nil,
			0,
			150*time.Millisecond, // snapshotInterval
			300*time.Millisecond, // idle
			5*time.Second,
		)
		if err != nil {
			t.Fatalf("error inesperado: %v", err)
		}

		var last string
		for s := range ch {
			last = s
		}

		if !strings.Contains(last, "HOLA") {
			t.Errorf("último snapshot no contiene 'HOLA': %q", last)
		}
	})

	t.Run("timeout duro con sleep 10", func(t *testing.T) {
		if testing.Short() {
			t.Skip("skip en modo corto: espera ~1s de timeout")
		}
		ctx := context.Background()
		start := time.Now()
		ch, err := PTYCaptureStream(
			ctx,
			"sleep", []string{"10"},
			50*time.Millisecond,
			nil,
			0,
			200*time.Millisecond, // snapshotInterval
			600*time.Millisecond, // idle
			1*time.Second,        // maxDur duro en 1s
		)
		if err != nil {
			t.Fatalf("error inesperado al arrancar: %v", err)
		}

		// Drenar completamente el canal.
		for range ch {
		}

		elapsed := time.Since(start)
		// La función debe retornar en menos de 3s, no esperar los 10s del sleep.
		if elapsed >= 3*time.Second {
			t.Errorf("la función tardó %v, se esperaba < 3s", elapsed)
		}
	})
}
