"""Tests for /api/backup/google-drive/* endpoints (Google Drive sync).

These tests verify the endpoint contract WITHOUT requiring real Google
credentials — the system should respond with sensible HTTP codes when
GOOGLE_CLIENT_ID/SECRET are absent (the default in CI).
"""
import os
import requests

BASE_URL = os.environ.get("REACT_APP_BACKEND_URL", "https://offline-billing-pro-2.preview.emergentagent.com").rstrip("/")


class TestGoogleDriveBackup:
    def test_status_works_without_creds(self, admin_session):
        """`/status` must always return 200 — even when keys are missing."""
        r = admin_session.get(f"{BASE_URL}/api/backup/google-drive/status", timeout=15)
        assert r.status_code == 200, r.text
        data = r.json()
        assert "configured" in data
        assert "connected" in data
        assert "auto_sync" in data
        # When no creds in .env, configured must be False
        # (this is the safe expectation; if user later adds keys, the test still passes
        # because configured will then be True — but for fresh CI it's False)

    def test_status_requires_admin(self):
        """Unauthenticated access → 401."""
        r = requests.get(f"{BASE_URL}/api/backup/google-drive/status", timeout=15)
        assert r.status_code == 401

    def test_connect_returns_503_when_unconfigured(self, admin_session):
        """If GOOGLE_CLIENT_ID is empty, /connect must 503 with a clear message."""
        # Check current configuration state first
        s = admin_session.get(f"{BASE_URL}/api/backup/google-drive/status", timeout=15).json()
        r = admin_session.get(f"{BASE_URL}/api/backup/google-drive/connect", timeout=15)
        if s.get("configured"):
            # Real keys present → endpoint returns 200 with an authorization_url
            assert r.status_code == 200, r.text
            data = r.json()
            assert data.get("authorization_url", "").startswith("https://accounts.google.com")
        else:
            assert r.status_code == 503, r.text
            assert "GOOGLE_CLIENT_ID" in r.json().get("detail", "")

    def test_settings_get_put(self, admin_session):
        """auto_sync flag round-trip."""
        # Default → can be either True or False from prior runs
        # Set to True
        r = admin_session.put(
            f"{BASE_URL}/api/backup/google-drive/settings",
            json={"auto_sync": True},
            timeout=15,
        )
        assert r.status_code == 200, r.text
        assert r.json()["auto_sync"] is True

        # GET back the value
        r = admin_session.get(f"{BASE_URL}/api/backup/google-drive/settings", timeout=15)
        assert r.status_code == 200
        assert r.json()["auto_sync"] is True

        # Toggle back to False
        r = admin_session.put(
            f"{BASE_URL}/api/backup/google-drive/settings",
            json={"auto_sync": False},
            timeout=15,
        )
        assert r.status_code == 200
        assert r.json()["auto_sync"] is False

    def test_list_remote_requires_connection(self, admin_session):
        """When not connected (no DB credentials), /list must 400 with a clear message."""
        # Ensure we're not connected — call disconnect first (idempotent)
        admin_session.post(f"{BASE_URL}/api/backup/google-drive/disconnect", timeout=15)
        r = admin_session.get(f"{BASE_URL}/api/backup/google-drive/list", timeout=15)
        assert r.status_code == 400, r.text
        assert "not connected" in r.json().get("detail", "").lower()

    def test_upload_requires_connection(self, admin_session):
        """Upload a non-existent backup → must return 404 (not 500) before reaching Drive."""
        r = admin_session.post(
            f"{BASE_URL}/api/backup/google-drive/upload/nonexistent_id_xyz",
            timeout=15,
        )
        assert r.status_code == 404, r.text

    def test_disconnect_is_idempotent(self, admin_session):
        """Disconnect when already disconnected → still 200."""
        r = admin_session.post(f"{BASE_URL}/api/backup/google-drive/disconnect", timeout=15)
        assert r.status_code == 200, r.text
        assert r.json().get("ok") is True

    def test_delete_remote_requires_connection(self, admin_session):
        """DELETE /<file_id> → 400 when no creds saved (not connected)."""
        admin_session.post(f"{BASE_URL}/api/backup/google-drive/disconnect", timeout=15)
        r = admin_session.delete(f"{BASE_URL}/api/backup/google-drive/any_file_id_xyz", timeout=15)
        assert r.status_code == 400, r.text
        assert "not connected" in r.json().get("detail", "").lower()

    def test_status_payload_shape(self, admin_session):
        """Status payload contract — must contain documented keys."""
        r = admin_session.get(f"{BASE_URL}/api/backup/google-drive/status", timeout=15)
        assert r.status_code == 200
        d = r.json()
        for key in ("configured", "connected", "account_email", "auto_sync", "connected_at"):
            assert key in d, f"missing key: {key}"
        # Without real keys, configured must be False
        assert d["configured"] is False
        assert d["connected"] is False

    def test_backup_endpoints_regression(self, admin_session):
        """Existing /api/backup endpoints (list & schedule) still work."""
        r = admin_session.get(f"{BASE_URL}/api/backup/list", timeout=20)
        assert r.status_code == 200, r.text
        assert isinstance(r.json(), list)
        r2 = admin_session.get(f"{BASE_URL}/api/backup/schedule", timeout=20)
        assert r2.status_code == 200, r2.text

    def test_ai_chat_regression(self, admin_session):
        """AI chat endpoint still responds after gdrive changes."""
        r = admin_session.post(
            f"{BASE_URL}/api/ai/chat",
            json={"message": "ping", "session_id": "regression_test_gdrive"},
            timeout=60,
        )
        assert r.status_code == 200, r.text
        assert "reply" in r.json() or "message" in r.json() or "response" in r.json()
