"""Tests for sync-to-4sat scraper push endpoints (gestion4sat)."""
import os
import pytest
import requests

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

ADMIN_EMAIL = "admin4sat@demo.com"
ADMIN_PASSWORD = "Test1234!"


@pytest.fixture(scope="module")
def admin_token():
    r = requests.post(
        f"{BASE_URL}/api/auth/login",
        json={"email": ADMIN_EMAIL, "password": ADMIN_PASSWORD},
        timeout=15,
    )
    assert r.status_code == 200, f"Login failed: {r.status_code} {r.text}"
    return r.json()["access_token"]


@pytest.fixture(scope="module")
def admin_headers(admin_token):
    return {"Authorization": f"Bearer {admin_token}", "Content-Type": "application/json"}


@pytest.fixture(scope="module")
def sample_dispositivo_id(admin_headers):
    """Fetch one existing g4s dispositivo id to test sync endpoint with."""
    r = requests.get(f"{BASE_URL}/api/gestion4sat/dispositivos?limit=1", headers=admin_headers, timeout=15)
    assert r.status_code == 200, f"listing dispositivos failed: {r.text}"
    data = r.json()
    disps = data.get("dispositivos", [])
    if not disps:
        pytest.skip("No dispositivos in DB to test sync")
    return disps[0]["id"]


# -------- PWA manifest static file --------
class TestPWAManifest:
    def test_portero_manifest_is_reachable(self):
        r = requests.get(f"{BASE_URL}/portero-manifest.json", timeout=10)
        assert r.status_code == 200
        data = r.json()
        assert data["short_name"] == "Portero GPS"
        assert data["start_url"] == "/portero/panel"
        assert data["scope"] == "/portero"
        assert data["display"] == "standalone"
        assert data["theme_color"] == "#09090b"


# -------- Sync endpoints existence + auth --------
class TestSyncTo4satAuth:
    def test_sync_single_requires_auth(self):
        r = requests.post(f"{BASE_URL}/api/gestion4sat/sync-to-4sat/some-id", timeout=15)
        assert r.status_code in (401, 403), f"expected 401/403 without token, got {r.status_code}"

    def test_sync_masivo_requires_auth(self):
        r = requests.post(f"{BASE_URL}/api/gestion4sat/sync-to-4sat-masivo", timeout=15)
        assert r.status_code in (401, 403)


class TestSyncTo4satAsAdmin:
    def test_sync_single_dispositivo_response(self, admin_headers, sample_dispositivo_id):
        """Endpoint must exist. Since 4sat creds probably not configured, expect 400 with
        'Credenciales 4sat.cl no configuradas'. If configured, expect 200 with 'synced' key."""
        r = requests.post(
            f"{BASE_URL}/api/gestion4sat/sync-to-4sat/{sample_dispositivo_id}",
            headers=admin_headers,
            timeout=60,
        )
        assert r.status_code in (200, 400, 401), f"Unexpected status {r.status_code}: {r.text}"
        if r.status_code == 400:
            body = r.json()
            detail = body.get("detail", "")
            assert "Credenciales" in detail or "no configuradas" in detail, f"Wrong 400 detail: {detail}"
        elif r.status_code == 200:
            body = r.json()
            assert "synced" in body or "message" in body

    def test_sync_single_dispositivo_not_found(self, admin_headers):
        """Unknown device id → 404 (only after admin_only + before creds check)."""
        # If creds are unconfigured, credentials check may come before 404 lookup depending on order.
        # Code order: _admin_only → find dispositivo → 404 if not found → gather data → creds.
        # So expect 404.
        r = requests.post(
            f"{BASE_URL}/api/gestion4sat/sync-to-4sat/non-existent-uuid-xxxx",
            headers=admin_headers,
            timeout=30,
        )
        assert r.status_code == 404, f"expected 404, got {r.status_code}: {r.text}"

    def test_sync_masivo_response(self, admin_headers):
        r = requests.post(
            f"{BASE_URL}/api/gestion4sat/sync-to-4sat-masivo",
            headers=admin_headers,
            timeout=120,
        )
        assert r.status_code in (200, 400), f"Unexpected status {r.status_code}: {r.text}"
        if r.status_code == 400:
            body = r.json()
            detail = body.get("detail", "")
            assert "Credenciales" in detail or "no configuradas" in detail
        else:
            body = r.json()
            assert "message" in body or "total" in body


# -------- Non-admin role → 403 --------
class TestSyncRoleGuard:
    def test_non_admin_gets_403(self):
        """Login as gerente (non-admin) and hit both endpoints."""
        r = requests.post(
            f"{BASE_URL}/api/auth/login",
            json={"email": "gerente@demo.com", "password": "Test1234!"},
            timeout=15,
        )
        if r.status_code != 200:
            pytest.skip("gerente user not available for role test")
        token = r.json()["access_token"]
        h = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
        r1 = requests.post(f"{BASE_URL}/api/gestion4sat/sync-to-4sat/anything", headers=h, timeout=15)
        r2 = requests.post(f"{BASE_URL}/api/gestion4sat/sync-to-4sat-masivo", headers=h, timeout=15)
        # gerente belongs to a company WITHOUT gestion_4sat module → likely 403 from module guard.
        # But even if module allowed, role guard should apply for non-admin.
        assert r1.status_code in (401, 403), f"gerente single: {r1.status_code} {r1.text}"
        assert r2.status_code in (401, 403), f"gerente masivo: {r2.status_code} {r2.text}"
