#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Fetch Medevio pending (ACTIVE) patient requests and return a pandas DataFrame.
Reads Bearer token from token.txt (single line, token only).
"""

import requests
import pandas as pd
import time
from pathlib import Path
from typing import List, Dict, Any

# CONFIG ---------------------------------------------------------------------
TOKEN_FILE = str(Path(__file__).resolve().parent.parent / "token.txt")  # centralized token
GRAPHQL_URL = "https://app.medevio.cz/graphql"
CLINIC_SLUG = "mudr-buzalkova"      # adjust if needed
LOCALE = "cs"
PAGE_SIZE = 50                      # how many items to request per page
REQUEST_WAIT = 0.2                  # seconds between requests to be polite
# ---------------------------------------------------------------------------

GRAPHQL_QUERY = r"""
query ClinicLegacyRequestList_ListPatientRequestsForClinic(
  $clinicSlug: String!,
  $queueId: String,
  $queueAssignment: QueueAssignmentFilter!,
  $state: PatientRequestState,
  $pageInfo: PageInfo!,
  $locale: Locale!
) {
  requests: listPatientRequestsForClinic(
    clinicSlug: $clinicSlug,
    queueId: $queueId,
    queueAssignment: $queueAssignment,
    state: $state,
    pageInfo: $pageInfo
  ) {
    id
    createdAt
    dueDate
    displayTitle(locale: $locale)
    doneAt
    removedAt
    priority
    evaluationResult(locale: $locale) {
      fields {
        name
        value
      }
    }
    clinicId
    extendedPatient {
      id
      identificationNumber
      kind
      name
      note
      owner { name surname }
      key
      status
      surname
      type
      user { id name surname }
      isUnknownPatient
    }
    lastMessage {
      createdAt
      id
      readAt
      sender { id name surname clinicId }
      text
    }
    queue { id name }
    reservations { id canceledAt done start }
    tags(onlyImportant: true) { id name color icon }
    priceWhenCreated
    currencyWhenCreated
  }
}
"""

def read_token(path: str) -> str:
    with open(path, "r", encoding="utf-8") as f:
        t = f.read().strip()
    if t.startswith("Bearer "):
        t = t.split(" ", 1)[1]
    return t

def fetch_requests(token: str,
                   clinic_slug: str = CLINIC_SLUG,
                   locale: str = LOCALE,
                   page_size: int = PAGE_SIZE) -> List[Dict[str, Any]]:
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json",
        "Accept": "application/json",
    }

    all_items: List[Dict[str, Any]] = []
    offset = 0

    while True:
        variables = {
            "clinicSlug": clinic_slug,
            "queueId": None,
            "queueAssignment": "ANY",
            "state": "ACTIVE",
            "pageInfo": {"first": page_size, "offset": offset},
            "locale": locale,
        }
        payload = {"query": GRAPHQL_QUERY, "variables": variables, "operationName": "ClinicLegacyRequestList_ListPatientRequestsForClinic"}

        r = requests.post(GRAPHQL_URL, json=payload, headers=headers, timeout=30)
        r.raise_for_status()
        js = r.json()

        # Basic error handling
        if "errors" in js:
            raise RuntimeError(f"GraphQL returned errors: {js['errors']}")

        items = js.get("data", {}).get("requests", [])
        if not items:
            break

        all_items.extend(items)

        # If fewer than requested, we are at the end
        if len(items) < page_size:
            break

        offset += page_size
        time.sleep(REQUEST_WAIT)

    return all_items

def flatten_item(item: Dict[str, Any]) -> Dict[str, Any]:
    patient = item.get("extendedPatient") or {}
    last_msg = item.get("lastMessage") or {}
    queue = item.get("queue") or {}

    # evaluationResult fields -> map of name:value (if exists)
    eval_map = {}
    eval_block = item.get("evaluationResult") or {}
    for fld in (eval_block.get("fields") or []):
        name = fld.get("name")
        value = fld.get("value")
        if name:
            eval_map[name] = value

    flat = {
        "id": item.get("id"),
        "createdAt": item.get("createdAt"),
        "dueDate": item.get("dueDate"),
        "displayTitle": item.get("displayTitle"),
        "doneAt": item.get("doneAt"),
        "removedAt": item.get("removedAt"),
        "priority": item.get("priority"),
        "clinicId": item.get("clinicId"),
        "patient_id": patient.get("id"),
        "patient_identificationNumber": patient.get("identificationNumber"),
        "patient_name": patient.get("name"),
        "patient_surname": patient.get("surname"),
        "patient_status": patient.get("status"),
        "lastMessage_id": last_msg.get("id"),
        "lastMessage_createdAt": last_msg.get("createdAt"),
        "lastMessage_text": last_msg.get("text"),
        "queue_id": queue.get("id"),
        "queue_name": queue.get("name"),
        "priceWhenCreated": item.get("priceWhenCreated"),
        "currencyWhenCreated": item.get("currencyWhenCreated"),
    }

    # merge evaluation fields (if any) prefixed by "eval_"
    for k, v in eval_map.items():
        flat[f"eval_{k}"] = v

    return flat

def to_dataframe(items: List[Dict[str, Any]]) -> pd.DataFrame:
    rows = [flatten_item(it) for it in items]
    df = pd.DataFrame(rows)
    # try parsing dates
    for col in ("createdAt", "dueDate", "doneAt", "lastMessage_createdAt", "removedAt"):
        if col in df.columns:
            df[col] = pd.to_datetime(df[col], errors="coerce")
    return df

def main():
    token = read_token(TOKEN_FILE)
    print("Fetching pending (ACTIVE) requests from Medevio...")
    items = fetch_requests(token)
    print(f"Fetched {len(items)} items.")
    df = to_dataframe(items)
    pd.set_option("display.max_rows", 20)
    pd.set_option("display.max_colwidth", 160)
    print(df.head(50))
    # optionally save
    df.to_excel("medevio_pending_requests.xlsx", index=False)
    print("Saved medevio_pending_requests.xlsx")

if __name__ == "__main__":
    main()
