"""
Backend tests for cross-module isolation bug fix.
Verifies:
1) admin4sat login and modulos_acceso persistence
2) POST /api/usuarios accepts modulos_acceso
3) GET /api/gestion4sat/tecnicos filters by module access / empresa
"""
import os
import time
import pytest
import requests

BASE_URL = os.environ.get("REACT_APP_BACKEND_URL", "https://doc-manager-111.preview.emergentagent.com").rstrip("/")

ADMIN4SAT_EMAIL = "admin4sat@demo.com"
ADMIN4SAT_PASS = "Test1234!"
ADMIN_DEMO_EMAIL = "admin@demo.com"
ADMIN_DEMO_PASS = "Test1234!"


def _login(email, password):
    r = requests.post(
        f"{BASE_URL}/api/auth/login",
        json={"email": email, "password": password},
        timeout=15,
    )
    assert r.status_code == 200, f"Login failed for {email}: {r.status_code} {r.text}"
    data = r.json()
    return data["access_token"], data["user"]


@pytest.fixture(scope="module")
def admin4sat_ctx():
    token, user = _login(ADMIN4SAT_EMAIL, ADMIN4SAT_PASS)
    return {"token": token, "user": user, "headers": {"Authorization": f"Bearer {token}"}}


@pytest.fixture(scope="module")
def admin_demo_ctx():
    token, user = _login(ADMIN_DEMO_EMAIL, ADMIN_DEMO_PASS)
    return {"token": token, "user": user, "headers": {"Authorization": f"Bearer {token}"}}


# ---- Authentication / module access ----

class TestAuthModuleAccess:
    def test_admin4sat_has_only_gestion_4sat(self, admin4sat_ctx):
        u = admin4sat_ctx["user"]
        assert u["email"] == ADMIN4SAT_EMAIL
        assert u["rol"] == "admin"
        assert u["modulos_acceso"] == ["gestion_4sat"], f"Unexpected modulos_acceso: {u.get('modulos_acceso')}"
        assert u["empresa_id"] == "f333b4b2-eb57-4e07-a23b-e2c59c412674"

    def test_admin_demo_has_no_modulos_acceso(self, admin_demo_ctx):
        u = admin_demo_ctx["user"]
        assert u["email"] == ADMIN_DEMO_EMAIL
        assert u["rol"] == "admin"
        # Multi-module user: modulos_acceso should be empty or missing
        assert not u.get("modulos_acceso"), f"admin@demo should be multi-module, got: {u.get('modulos_acceso')}"


# ---- POST /api/usuarios ----

class TestUsuariosCreate:
    _created_ids = []

    def test_create_user_with_modulos_acceso(self, admin4sat_ctx):
        ts = int(time.time())
        email = f"test_4sat_newuser_{ts}@demo.com"
        payload = {
            "nombre": "Test Tecnico 4SAT",
            "email": email,
            "password": "Test1234!",
            "rol": "tecnico",
            "modulos_acceso": ["gestion_4sat"],
        }
        r = requests.post(
            f"{BASE_URL}/api/usuarios",
            json=payload,
            headers=admin4sat_ctx["headers"],
            timeout=15,
        )
        assert r.status_code == 200, f"Expected 200, got {r.status_code}: {r.text}"
        data = r.json()
        assert data["email"] == email
        assert "id" in data
        TestUsuariosCreate._created_ids.append((data["id"], email))

    def test_created_user_can_login_and_has_modulos_acceso(self):
        assert TestUsuariosCreate._created_ids, "Precondition: user must be created first"
        _, email = TestUsuariosCreate._created_ids[-1]
        token, user = _login(email, "Test1234!")
        assert user["modulos_acceso"] == ["gestion_4sat"], f"modulos_acceso not persisted: {user.get('modulos_acceso')}"
        assert user["rol"] == "tecnico"
        # Empresa should be inherited from creating admin (empresa 4sat)
        assert user["empresa_id"] == "f333b4b2-eb57-4e07-a23b-e2c59c412674"


# ---- GET /api/gestion4sat/tecnicos ----

class TestGestion4satTecnicos:
    def test_tecnicos_endpoint_returns_list(self, admin4sat_ctx):
        r = requests.get(
            f"{BASE_URL}/api/gestion4sat/tecnicos",
            headers=admin4sat_ctx["headers"],
            timeout=15,
        )
        assert r.status_code == 200, f"{r.status_code}: {r.text}"
        data = r.json()
        assert "tecnicos" in data
        assert isinstance(data["tecnicos"], list)

    def test_tecnicos_filtered_by_module_or_empresa(self, admin4sat_ctx):
        r = requests.get(
            f"{BASE_URL}/api/gestion4sat/tecnicos",
            headers=admin4sat_ctx["headers"],
            timeout=15,
        )
        assert r.status_code == 200
        tecnicos = r.json()["tecnicos"]
        empresa_4sat = "f333b4b2-eb57-4e07-a23b-e2c59c412674"
        # Every returned tecnico must have gestion_4sat access OR belong to 4sat empresa
        # (endpoint returns id, nombre, email, rol, modulos_acceso; empresa_id NOT included)
        # So we validate via presence of modulos_acceso field logic
        for t in tecnicos:
            has_4sat = "gestion_4sat" in (t.get("modulos_acceso") or [])
            # If they don't have 4sat access, we need to verify empresa. But field not returned.
            # Fetch full user via login is not feasible. Assume result set is properly filtered
            # and at minimum: the admin4sat user itself should appear.
            assert isinstance(t.get("id"), str)
        # Ensure the admin4sat user or any user with gestion_4sat is present
        assert any(
            "gestion_4sat" in (t.get("modulos_acceso") or []) or t.get("email") == ADMIN4SAT_EMAIL
            for t in tecnicos
        ), "No expected users found in tecnicos list"

    def test_tecnicos_does_not_leak_other_empresa_admins(self, admin4sat_ctx):
        """Users like gerente@demo.com (empresa Demo, no gestion_4sat access) should NOT appear."""
        r = requests.get(
            f"{BASE_URL}/api/gestion4sat/tecnicos",
            headers=admin4sat_ctx["headers"],
            timeout=15,
        )
        tecnicos = r.json()["tecnicos"]
        emails = [t.get("email") for t in tecnicos]
        # gerente@demo.com belongs to Empresa Demo S.A. with no gestion_4sat access
        assert "gerente@demo.com" not in emails, f"Leaked user from other empresa: gerente@demo.com. Emails: {emails}"


if __name__ == "__main__":
    pytest.main([__file__, "-v"])
