import httpx from app.config import settings as get_settings class HealthieClient: def __init__(self): s = get_settings() self._client = httpx.Client( base_url=s.healthie_api_base_url, headers={ "Content-Type": "application/json", "Authorization": f"Basic {s.healthie_api_key}", "AuthorizationSource": "API", }, timeout=30.0, ) def query(self, query: str, variables: dict | None = None) -> dict: payload = {"query": query} if variables: payload["variables"] = variables resp = self._client.post("/", json=payload) resp.raise_for_status() data = resp.json() if "errors" in data: raise ValueError(f"Healthie API error: {data['errors']}") return data["data"] def fetch_form_definition(self) -> list[dict]: """Fetch all modules for the form template.""" result = self.query( """ query($formId: ID!) { customModuleForm(id: $formId) { custom_modules { id label mod_type options metadata position required sublabel } } } """, {"formId": get_settings().form_template_id}, ) return result["customModuleForm"]["custom_modules"] def create_client(self, data: dict) -> str: """Create a new patient in Healthie. Returns client ID.""" result = self.query( """ mutation($input: createClientInput!) { createClient(input: $input) { user { id } messages { field message } } } """, {"input": data}, ) payload = result.get("createClient") or {} user = payload.get("user") if user: return user["id"] msgs = payload.get("messages") or [] raise ValueError(f"createClient failed: {msgs}") def submit_form_answers(self, user_id: str, answers: list[dict]) -> str: """Submit all form answers. Returns form_answer_group ID.""" result = self.query( """ mutation($input: createFormAnswerGroupInput!) { createFormAnswerGroup(input: $input) { form_answer_group { id } } } """, { "input": { "custom_module_form_id": get_settings().form_template_id, "user_id": user_id, "finished": True, "marked_complete": True, "form_answers": answers, } }, ) return result["createFormAnswerGroup"]["form_answer_group"]["id"] def get_presigned_url(self, form_answer_id: str, filename: str, byte_size: int, checksum: str, content_type: str) -> dict: """Request a presigned upload URL for a file attachment.""" result = self.query( """ mutation($input: createFormAnswerFileAttachmentUploadUrlInput!) { createFormAnswerFileAttachmentUploadUrl(input: $input) { upload_id upload_url } } """, { "input": { "form_answer_id": form_answer_id, "filename": filename, "byte_size": byte_size, "checksum": checksum, "content_type": content_type, } }, ) data = result["createFormAnswerFileAttachmentUploadUrl"] return { "uploadId": data["upload_id"], "presignedUrl": data["upload_url"], } def confirm_file_attachment(self, form_answer_id: str, upload_id: str) -> bool: """Confirm file attachment after upload.""" self.query( """ mutation($input: createFormAnswerFileAttachmentInput!) { createFormAnswerFileAttachment(input: $input) { form_answer_file_attachment { id } } } """, { "input": { "form_answer_id": form_answer_id, "upload_id": upload_id, } }, ) return True healthie = HealthieClient()