Is this code correct: #!/usr/bin/env python3
"""
talk2docs_util_sp.py
────────────────────
Upload PDFs to Nucleus Talk2Docs and query them using a *service-principal*.
No az CLI, no browser, tokens auto-refresh.

Required env vars
-----------------
AZURE_TENANT_ID         your AAD tenant (GUID)
AZURE_CLIENT_ID         the App-ID of the registration
AZURE_CLIENT_SECRET     the client secret
NUC_HOST                dev.nucleus.aks.azure.ubsdev.net (default)
NUC_ORG_ID              <organisation GUID>   ✔
NUC_SVC_ID              <service GUID>        ✔
AZURE_RESOURCE          api://processing-document-service (.default implied)

pip install requests azure-identity
"""

from __future__ import annotations
import os, sys, json, time, argparse, pathlib
from datetime import datetime
import requests
from azure.identity import ClientSecretCredential, CredentialUnavailableError

# ───────────────────────────────────────────── configuration

HOST       = os.getenv("NUC_HOST", "dev.nucleus.aks.azure.ubsdev.net")
ORG_ID     = os.getenv("NUC_ORG_ID")  or sys.exit("NUC_ORG_ID env var missing")
SERVICE_ID = os.getenv("NUC_SVC_ID")  or sys.exit("NUC_SVC_ID env var missing")
RESOURCE   = os.getenv("AZURE_RESOURCE", "api://processing-document-service")
SCOPE      = f"{RESOURCE}/.default"

for v in ("AZURE_TENANT_ID", "AZURE_CLIENT_ID", "AZURE_CLIENT_SECRET"):
    if not os.getenv(v):
        sys.exit(f"Env var {v} is required for service-principal auth")

# ───────────────────────────────────────────── token helper

cred = ClientSecretCredential(
    tenant_id   = os.environ["AZURE_TENANT_ID"],
    client_id   = os.environ["AZURE_CLIENT_ID"],
    client_secret = os.environ["AZURE_CLIENT_SECRET"],
)

def bearer() -> str:
    """Silently fetch a cached / fresh token; auto-refresh when <5 min left."""
    try:
        return cred.get_token(SCOPE).token
    except CredentialUnavailableError as e:
        sys.exit(f"Token acquisition failed: {e}")

def _hdr() -> dict[str, str]:
    return {"Authorization": f"Bearer {bearer()}"}

# ───────────────────────────────────────────── Talk2Docs wrappers

def upload_pdf(path: pathlib.Path, labels: list[str]) -> str:
    url = (f"https://{HOST}/api/v1/processing-document-service/"
           f"organizations/{ORG_ID}/services/{SERVICE_ID}/process")
    payload = {"documentName": path.name, "labels": labels}
    files   = {
        "file": (path.name, open(path, "rb"), "application/pdf"),
        "uploadData": ("meta.json", json.dumps(payload), "application/json"),
    }
    r = requests.post(url, headers=_hdr(), files=files, verify=False, timeout=30)
    r.raise_for_status()
    doc_id = r.json()["documentId"]
    print(f"[{datetime.utcnow():%H:%M:%S}] uploaded {path.name} ⇒ {doc_id}")
    return doc_id

def wait_until_indexed(doc_id: str, *, timeout=180, poll=6) -> None:
    url = f"https://{HOST}/api/v1/processing-document-service/documents/{doc_id}/status"
    deadline = time.time() + timeout
    while time.time() < deadline:
        state = requests.get(url, headers=_hdr(), verify=False).json().get("state")
        if state == "INDEXED":
            print("document indexed ✓")
            return
        print("indexing…", state)
        time.sleep(poll)
    print("timed-out waiting for indexing (continuing)")

def ask(question: str, labels: list[str]) -> None:
    url  = f"https://{HOST}/api/v1/talk2docs/query"
    body = {
        "queryMessages": [{"role": "user", "content": question}],
        "filter": {"documentLabels": labels},
    }
    r = requests.post(url, headers=_hdr(), json=body, verify=False, timeout=60)
    r.raise_for_status()
    print("\n▶︎ ANSWER\n", r.json()["content"])

# ───────────────────────────────────────────── CLI glue

def main() -> None:
    ap = argparse.ArgumentParser(prog="talk2docs_util_sp",
                                 description="Upload and/or query Talk2Docs")
    ap.add_argument("--upload", type=pathlib.Path, help="PDF to upload")
    ap.add_argument("--ask",    help="Question to ask Talk2Docs")
    ap.add_argument("--labels", nargs="+", default=["poc"], help="Document labels")
    ap.add_argument("--skip-wait", action="store_true",
                    help="Don’t wait for indexing")
    a = ap.parse_args()

    if not a.upload and not a.ask:
        ap.error("Specify --upload, --ask, or both")

    if a.upload:
        doc = upload_pdf(a.upload, a.labels)
        if not a.skip_wait:
            wait_until_indexed(doc)

    if a.ask:
        ask(a.ask, a.labels)

if __name__ == "__main__":
    main()