"""Tests para browser_profile_register.

browser_profile_register hace POST al service osint_db (perfil + cuentas). Aqui se
mockea el helper compartido `post_json` (ligado en el modulo por el `from
browser._osint_db_client import post_json`) para NO tocar el service real. Se valida
el armado de los payloads y el conteo/errores de cuentas.
"""

import os
import sys

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

import browser.browser_profile_register as bpr
from browser.browser_profile_register import browser_profile_register


class _PostSpy:
    """Registra cada (path, payload) y devuelve respuestas segun el path."""

    def __init__(self, profile_resp, account_resp):
        self.calls = []  # lista de (path, payload)
        self.profile_resp = profile_resp
        self.account_resp = account_resp

    def __call__(self, base_url, path, payload):
        self.calls.append((path, payload))
        if path == "/api/browser-profile":
            return self.profile_resp
        return self.account_resp


def test_golden_registra_perfil_con_dos_cuentas(monkeypatch):
    spy = _PostSpy(
        profile_resp={"status": "ok", "profile_dir": "Profile 1", "inserted": 1, "updated": 0},
        account_resp={"status": "ok", "id": "x", "inserted": 1, "updated": 0},
    )
    monkeypatch.setattr(bpr, "post_json", spy)

    res = browser_profile_register(
        "Profile 1",
        label="Persona Maria",
        persona="maria_ficticia",
        purpose="rastreo",
        tags=["osint", "sock-puppet"],
        accounts=[
            {"service": "gmail", "identity": "maria@example.com",
             "secret_ref": "pass show osint/p1/gmail"},
            {"service": "x", "identity": "@maria_fake", "role": "primary"},
        ],
    )

    assert res["status"] == "ok"
    assert res["profile_dir"] == "Profile 1"
    assert res["accounts"] == 2
    assert res["account_errors"] == []

    # 1 POST de perfil + 2 POST de cuentas = 3 llamadas.
    assert len(spy.calls) == 3
    profile_path, profile_payload = spy.calls[0]
    assert profile_path == "/api/browser-profile"
    assert profile_payload["profile_dir"] == "Profile 1"
    assert profile_payload["label"] == "Persona Maria"
    assert profile_payload["tags"] == ["osint", "sock-puppet"]
    assert profile_payload["status"] == "active"
    # user_data_dir vacio no debe ir en el payload.
    assert "user_data_dir" not in profile_payload

    # Las cuentas llevan profile_dir y solo las claves no vacias.
    acc_path, acc_payload = spy.calls[1]
    assert acc_path == "/api/browser-profile/account"
    assert acc_payload["profile_dir"] == "Profile 1"
    assert acc_payload["service"] == "gmail"
    assert acc_payload["secret_ref"] == "pass show osint/p1/gmail"


def test_edge_cuenta_invalida_se_reporta_y_no_se_envia(monkeypatch):
    spy = _PostSpy(
        profile_resp={"status": "ok", "profile_dir": "osint_01", "inserted": 0, "updated": 1},
        account_resp={"status": "ok"},
    )
    monkeypatch.setattr(bpr, "post_json", spy)

    res = browser_profile_register(
        "osint_01",
        accounts=[
            {"service": "gmail"},                       # falta identity -> invalida
            {"service": "x", "identity": "@ok"},        # valida
        ],
    )

    assert res["status"] == "ok"
    assert res["accounts"] == 1                          # solo la valida se registro
    assert len(res["account_errors"]) == 1
    assert "identity" in res["account_errors"][0]["error"]
    # La cuenta invalida NO genero POST: 1 perfil + 1 cuenta valida = 2 llamadas.
    assert len(spy.calls) == 2


def test_error_post_perfil_falla_devuelve_status_error(monkeypatch):
    spy = _PostSpy(
        profile_resp={"status": "error", "error": "service osint_db inaccesible"},
        account_resp={"status": "ok"},
    )
    monkeypatch.setattr(bpr, "post_json", spy)

    res = browser_profile_register("Profile 1", accounts=[{"service": "g", "identity": "a@b"}])

    assert res["status"] == "error"
    assert "inaccesible" in res["error"]
    # Si el perfil falla, NO se intentan las cuentas: solo 1 llamada (la del perfil).
    assert len(spy.calls) == 1
