package browser

import (
	"errors"
	"testing"
)

// TestCdpEvalInFrame_guards cubre precondiciones sin Chrome.
func TestCdpEvalInFrame_guards(t *testing.T) {
	t.Run("conexion nula", func(t *testing.T) {
		if _, err := CdpEvalInFrame(nil, "f1", "1"); err == nil {
			t.Fatal("esperaba error con conexion nula")
		}
	})
	t.Run("frameID vacio", func(t *testing.T) {
		if _, err := CdpEvalInFrame(&CDPConn{}, "", "1"); err == nil {
			t.Fatal("esperaba error con frameID vacio")
		}
	})
}

// TestFrameCtxCache cubre el núcleo puro del cache de contextos por frame.
func TestFrameCtxCache(t *testing.T) {
	t.Run("golden: set/get devuelve el ctxId cacheado", func(t *testing.T) {
		c := newFrameCtxCache()
		if _, ok := c.get("frameA"); ok {
			t.Fatal("cache recién creado no debería tener frameA")
		}
		c.set("frameA", 42)
		id, ok := c.get("frameA")
		if !ok || id != 42 {
			t.Fatalf("get(frameA) = (%d,%v), esperaba (42,true)", id, ok)
		}
	})

	t.Run("edge: frames distintos no se pisan", func(t *testing.T) {
		c := newFrameCtxCache()
		c.set("frameA", 1)
		c.set("frameB", 2)
		if id, _ := c.get("frameA"); id != 1 {
			t.Errorf("frameA = %d, esperaba 1", id)
		}
		if id, _ := c.get("frameB"); id != 2 {
			t.Errorf("frameB = %d, esperaba 2", id)
		}
	})

	t.Run("invalidate: tras invalidar, get falla (fuerza recrear mundo)", func(t *testing.T) {
		c := newFrameCtxCache()
		c.set("frameA", 7)
		c.invalidate("frameA")
		if _, ok := c.get("frameA"); ok {
			t.Error("tras invalidate, get(frameA) debería fallar")
		}
	})
}

// TestIsStaleContextError cubre el discriminador puro que decide si reintentar
// recreando el isolated world.
func TestIsStaleContextError(t *testing.T) {
	cases := []struct {
		name string
		err  error
		want bool
	}{
		{"nil no es stale", nil, false},
		{"error generico no es stale", errors.New("boom"), false},
		{"Cannot find context es stale", errors.New("cdp error: Cannot find context with specified id"), true},
		{"Execution context was destroyed es stale", errors.New("Execution context was destroyed"), true},
		{"uniqueContextId es stale", errors.New("invalid uniqueContextId"), true},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			if got := isStaleContextError(tc.err); got != tc.want {
				t.Errorf("isStaleContextError(%v) = %v, esperaba %v", tc.err, got, tc.want)
			}
		})
	}
}
