package browser

import (
	"fmt"
	"os"
)

// CdpSetFileInput sube archivos a un <input type="file"> identificado por el
// selector CSS. Resuelve el nodo via DOM.getDocument + DOM.querySelector y luego
// asigna los archivos con DOM.setFileInputFiles. Util para automatizar formularios
// de subida sin simular el dialogo nativo de seleccion de archivos.
//
// Cada path de paths se valida con os.Stat ANTES de enviar el comando: si alguno
// no existe (o no es accesible) se devuelve error inmediato sin tocar el DOM. Los
// paths deben ser absolutos y accesibles por el proceso de Chrome (ver Gotchas en
// el .md): Chrome lee los archivos desde su propio contexto, no desde el de este
// programa.
func CdpSetFileInput(c *CDPConn, selector string, paths []string) error {
	if c == nil {
		return fmt.Errorf("cdp set file input: conexion nula")
	}
	if selector == "" {
		return fmt.Errorf("cdp set file input: selector vacio")
	}
	if len(paths) == 0 {
		return fmt.Errorf("cdp set file input: lista de paths vacia")
	}

	// Validar que cada path exista en disco antes de mandar nada a Chrome.
	for _, p := range paths {
		if p == "" {
			return fmt.Errorf("cdp set file input: path vacio en la lista")
		}
		if _, err := os.Stat(p); err != nil {
			if os.IsNotExist(err) {
				return fmt.Errorf("cdp set file input: el archivo no existe: %q", p)
			}
			return fmt.Errorf("cdp set file input: no se puede acceder al archivo %q: %w", p, err)
		}
	}

	// Obtener el nodo raiz del documento.
	docRes, err := c.sendCDP("DOM.getDocument", map[string]any{"depth": 0})
	if err != nil {
		return fmt.Errorf("cdp set file input: DOM.getDocument: %w", err)
	}
	root, ok := docRes["root"].(map[string]any)
	if !ok {
		return fmt.Errorf("cdp set file input: respuesta de DOM.getDocument sin root")
	}
	rootNodeID, ok := root["nodeId"].(float64)
	if !ok {
		return fmt.Errorf("cdp set file input: DOM.getDocument sin nodeId raiz")
	}

	// Resolver el input por selector.
	qsRes, err := c.sendCDP("DOM.querySelector", map[string]any{
		"nodeId":   int(rootNodeID),
		"selector": selector,
	})
	if err != nil {
		return fmt.Errorf("cdp set file input: DOM.querySelector %q: %w", selector, err)
	}
	nodeIDVal, ok := qsRes["nodeId"].(float64)
	if !ok || int(nodeIDVal) == 0 {
		return fmt.Errorf("cdp set file input: el selector %q no coincide con ningun elemento", selector)
	}

	// Asignar los archivos al input.
	files := make([]any, len(paths))
	for i, p := range paths {
		files[i] = p
	}
	if _, err := c.sendCDP("DOM.setFileInputFiles", map[string]any{
		"files":  files,
		"nodeId": int(nodeIDVal),
	}); err != nil {
		return fmt.Errorf("cdp set file input: DOM.setFileInputFiles en %q: %w", selector, err)
	}

	return nil
}
