package browser

import (
	"fmt"
	"strconv"
	"strings"
)

// CdpClick hace click en el primer elemento que coincide con el selector CSS.
// Obtiene las coordenadas del elemento via Runtime.evaluate y luego despacha
// eventos mousedown, mouseup y click via Input.dispatchMouseEvent.
func CdpClick(c *CDPConn, selector string) error {
	if c == nil {
		return fmt.Errorf("cdp click: conexion nula")
	}

	// Obtener coordenadas del centro del elemento
	js := fmt.Sprintf(`(function() {
		var el = document.querySelector(%q);
		if (!el) return null;
		var r = el.getBoundingClientRect();
		return JSON.stringify({x: r.left + r.width/2, y: r.top + r.height/2});
	})()`, selector)

	coordStr, err := CdpEvaluate(c, js)
	if err != nil {
		return fmt.Errorf("cdp click: obtener coordenadas de %q: %w", selector, err)
	}
	if coordStr == "" || coordStr == "null" {
		return fmt.Errorf("cdp click: elemento %q no encontrado en el DOM", selector)
	}

	// Parsear "{x:...,y:...}" — CdpEvaluate ya retorna el JSON como string
	coordStr = strings.Trim(coordStr, `"`)
	x, y, err := parseCoords(coordStr)
	if err != nil {
		return fmt.Errorf("cdp click: parsear coordenadas %q: %w", coordStr, err)
	}

	// Hacer scroll al elemento para que este visible
	scrollJS := fmt.Sprintf(`document.querySelector(%q).scrollIntoView({block:'center'})`, selector)
	if _, err := CdpEvaluate(c, scrollJS); err != nil {
		// No es fatal si el scroll falla
		_ = err
	}

	// Despachar mousedown
	mouseParams := map[string]any{
		"type":       "mousePressed",
		"x":          x,
		"y":          y,
		"button":     "left",
		"clickCount": 1,
	}
	if _, err := c.sendCDP("Input.dispatchMouseEvent", mouseParams); err != nil {
		return fmt.Errorf("cdp click: mousedown: %w", err)
	}

	// Despachar mouseup
	mouseParams["type"] = "mouseReleased"
	if _, err := c.sendCDP("Input.dispatchMouseEvent", mouseParams); err != nil {
		return fmt.Errorf("cdp click: mouseup: %w", err)
	}

	return nil
}

// parseCoords extrae x e y de un string JSON como {"x":100,"y":200}.
func parseCoords(s string) (float64, float64, error) {
	// Buscar valores x e y manualmente para evitar dependencia de encoding/json
	s = strings.TrimSpace(s)
	s = strings.TrimPrefix(s, "{")
	s = strings.TrimSuffix(s, "}")

	var x, y float64
	for part := range strings.SplitSeq(s, ",") {
		kv := strings.SplitN(strings.TrimSpace(part), ":", 2)
		if len(kv) != 2 {
			continue
		}
		k := strings.Trim(strings.TrimSpace(kv[0]), `"`)
		v, err := strconv.ParseFloat(strings.TrimSpace(kv[1]), 64)
		if err != nil {
			return 0, 0, fmt.Errorf("parsear valor %q: %w", kv[1], err)
		}
		switch k {
		case "x":
			x = v
		case "y":
			y = v
		}
	}
	return x, y, nil
}
