"""Tests para whatsapp_open_chat.

whatsapp_open_chat compone cuatro primitivas CDP (cdp_eval, cdp_type_chars,
cdp_press_key, cdp_click_xy) y requiere un Chrome vivo. Aqui se mockean las cuatro
con monkeypatch sobre el modulo `browser.whatsapp_open_chat` (donde quedan ligados
los nombres por el `from browser.X import Y`), de modo que NO hace falta Chrome.

Las llamadas a cdp_eval que importan son dos:
  - la del ancla (querySelectorAll '#side span[title]') -> devuelve coords JSON.
  - la de verificacion (footer contenteditable aria-label) -> devuelve el label.
El resto de cdp_eval (focus/select del input) devuelven un value inocuo.
"""

import json
import os
import sys

sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))

import browser.whatsapp_open_chat as woc
from browser.whatsapp_open_chat import whatsapp_open_chat


# --- Fakes -----------------------------------------------------------------

def _fake_cdp_eval_factory(anchor_value, composer_value):
    """Devuelve un fake de cdp_eval que distingue el ancla del composer.

    - Expresion con 'span[title]' (busqueda del ancla) -> {"value": anchor_value}.
    - Expresion con 'contenteditable' (composer) -> {"value": composer_value}.
    - Cualquier otra (focus/select del input) -> {"value": None} inocuo.
    """

    def _fake(expr, *, port=9222, target_url_substr=""):
        if "span[title]" in expr:
            return {"ok": True, "value": anchor_value, "error": "", "target_url": ""}
        if "contenteditable" in expr:
            return {"ok": True, "value": composer_value, "error": "", "target_url": ""}
        return {"ok": True, "value": None, "error": "", "target_url": ""}

    return _fake


class _Spy:
    """Registra los argumentos posicionales de cada llamada."""

    def __init__(self, ret=None):
        self.calls = []
        self.ret = ret if ret is not None else {"ok": True}

    def __call__(self, *args, **kwargs):
        self.calls.append((args, kwargs))
        return self.ret


def _patch_io(monkeypatch, *, anchor_value, composer_value, click_spy=None):
    """Mockea las cuatro primitivas + time.sleep en el modulo woc."""
    monkeypatch.setattr(woc, "cdp_eval",
                        _fake_cdp_eval_factory(anchor_value, composer_value))
    monkeypatch.setattr(woc, "cdp_type_chars", lambda *a, **k: {"ok": True})
    monkeypatch.setattr(woc, "cdp_press_key", lambda *a, **k: {"ok": True})
    monkeypatch.setattr(woc, "cdp_click_xy", click_spy or (lambda *a, **k: {"ok": True}))
    monkeypatch.setattr(woc.time, "sleep", lambda *a, **k: None)


# --- Tests -----------------------------------------------------------------

def test_golden_abre_chat_y_verifica_composer(monkeypatch):
    coords = json.dumps({"x": 180, "y": 240})
    label = "Escribir un mensaje para el grupo NOTAS WASAP"
    _patch_io(monkeypatch, anchor_value=coords, composer_value=label)

    res = whatsapp_open_chat("NOTAS WASAP", port=9222, target_url_substr="whatsapp")

    assert res["opened"] is True
    assert res["name"] == "NOTAS WASAP"
    assert res["composer_label"] == label
    assert res["coords"] == {"x": 180, "y": 240}


def test_edge_ancla_no_encontrada_opened_false(monkeypatch):
    # El ancla no existe: cdp_eval del span[title] devuelve value None.
    _patch_io(monkeypatch, anchor_value=None, composer_value="irrelevante")

    res = whatsapp_open_chat("Contacto Inexistente", port=9222,
                             target_url_substr="whatsapp")

    assert res["opened"] is False
    assert res["name"] == "Contacto Inexistente"
    assert "no encontrado" in res["reason"]
    # Sin coords ni composer_label cuando no se encuentra el ancla.
    assert "coords" not in res
    assert "composer_label" not in res


def test_click_usa_coords_devueltas_por_el_ancla(monkeypatch):
    coords = json.dumps({"x": 333, "y": 444})
    label = "Escribir un mensaje para el grupo NOTAS WASAP"
    click_spy = _Spy(ret={"ok": True})
    _patch_io(monkeypatch, anchor_value=coords, composer_value=label,
              click_spy=click_spy)

    res = whatsapp_open_chat("NOTAS WASAP", port=9222, target_url_substr="whatsapp")

    # Se llamo a cdp_click_xy exactamente una vez con las coords del ancla.
    assert len(click_spy.calls) == 1
    args, kwargs = click_spy.calls[0]
    assert args[0] == 333
    assert args[1] == 444
    assert kwargs["port"] == 9222
    assert kwargs["target_url_substr"] == "whatsapp"
    assert res["opened"] is True
