package browser

import (
	"fmt"
	"time"
)

// CdpWaitLoad espera a que la página actual termine de cargar completamente.
// Bloquea hasta recibir el evento CDP Page.loadEventFired (sin polling): suscribe
// el evento via OnEvent y espera en un canal con timeout. Antes de esperar hace un
// fast path comprobando document.readyState — si la página ya está "complete",
// retorna de inmediato sin armar el handler.
// Retorna error si el timeout se agota o si no logra habilitar el dominio Page.
func CdpWaitLoad(c *CDPConn, timeout time.Duration) error {
	if c == nil {
		return fmt.Errorf("cdp wait load: conexion nula")
	}
	if timeout <= 0 {
		timeout = 30 * time.Second
	}

	// Fast path: si el documento ya terminó de cargar, no esperamos eventos.
	if rs, err := CdpEvaluate(c, "document.readyState"); err == nil && rs == "complete" {
		return nil
	}

	// Habilitar Page (idempotente, cacheado) y suscribir el evento de carga.
	if err := c.ensurePage(); err != nil {
		return fmt.Errorf("cdp wait load: Page.enable: %w", err)
	}
	loaded := make(chan struct{}, 1)
	cancel := c.OnEvent("Page.loadEventFired", func(_ string, _ map[string]any) {
		select {
		case loaded <- struct{}{}:
		default:
		}
	})
	defer cancel()

	// Re-chequear readyState tras suscribir: si la carga terminó entre el fast
	// path y el registro del handler, ya no llegaría el evento (carrera) — lo
	// captamos aquí en vez de colgarnos hasta el timeout.
	if rs, err := CdpEvaluate(c, "document.readyState"); err == nil && rs == "complete" {
		return nil
	}

	select {
	case <-loaded:
		return nil
	case <-time.After(timeout):
		return fmt.Errorf("cdp wait load: pagina no cargo despues de %s", timeout)
	}
}
