import json
import types


def _configure_paths(monkeypatch, gds, tmp_path):
    credentials_file = tmp_path / "google_credentials.json"
    token_file = tmp_path / "google_token.json"
    legacy_file = tmp_path / "google_token.pickle"
    credentials_file.write_text("{}", encoding="utf-8")
    monkeypatch.setattr(gds, "CREDENTIALS_FILE", str(credentials_file))
    monkeypatch.setattr(gds, "TOKEN_FILE", str(token_file))
    monkeypatch.setattr(gds, "_LEGACY_PICKLE_FILE", str(legacy_file))
    return credentials_file, token_file, legacy_file


def test_production_runtime_never_starts_interactive_drive_auth(monkeypatch, tmp_path):
    import services.google_drive_service as gds

    _configure_paths(monkeypatch, gds, tmp_path)
    monkeypatch.setenv("GOOGLE_DRIVE_ALLOW_INTERACTIVE_AUTH", "true")
    monkeypatch.setenv("FLASK_ENV", "production")

    class ExplodingFlow:
        @staticmethod
        def from_client_secrets_file(*_args, **_kwargs):
            raise AssertionError("browser OAuth must not run in production")

    monkeypatch.setattr(gds, "InstalledAppFlow", ExplodingFlow)

    service = gds.GoogleDriveService()

    assert service.authenticate() is False
    assert service.last_error_kind == "reauthorization_required"
    assert "授權檔不存在" in service.last_error


def test_drive_auth_readiness_refreshes_and_persists_json_token(monkeypatch, tmp_path):
    import services.google_drive_service as gds

    _, token_file, _ = _configure_paths(monkeypatch, gds, tmp_path)
    token_file.write_text(json.dumps({"token": "old"}), encoding="utf-8")

    class FakeCredentials:
        valid = False
        expired = True
        refresh_token = "refresh-token"

        def refresh(self, _request):
            self.valid = True
            self.expired = False

        def to_json(self):
            return json.dumps({"token": "new-token", "refresh_token": self.refresh_token})

    fake_credentials = FakeCredentials()
    monkeypatch.setattr(
        gds,
        "Credentials",
        types.SimpleNamespace(
            from_authorized_user_info=lambda _token_data, _scopes: fake_credentials
        ),
    )

    service = gds.GoogleDriveService()
    status = service.check_auth_readiness(refresh_expired=True)

    assert status["ready"] is True
    assert status["kind"] == "ready"
    assert service.last_error_kind is None
    assert json.loads(token_file.read_text(encoding="utf-8"))["token"] == "new-token"


def test_drive_auth_readiness_requires_refresh_token(monkeypatch, tmp_path):
    import services.google_drive_service as gds

    _, token_file, _ = _configure_paths(monkeypatch, gds, tmp_path)
    token_file.write_text(json.dumps({"token": "stale"}), encoding="utf-8")

    class FakeCredentials:
        valid = False
        expired = False
        refresh_token = None

    monkeypatch.setattr(
        gds,
        "Credentials",
        types.SimpleNamespace(
            from_authorized_user_info=lambda _token_data, _scopes: FakeCredentials()
        ),
    )

    service = gds.GoogleDriveService()
    status = service.check_auth_readiness(refresh_expired=True)

    assert status["ready"] is False
    assert status["kind"] == "reauthorization_required"
    assert service.last_error_kind == "reauthorization_required"
    assert "缺少可刷新憑證" in service.last_error
