#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import pymysql
import requests
from pathlib import Path
from datetime import datetime
from dateutil import parser
import time
import sys

# ================================
# UTF-8 SAFE OUTPUT (Windows friendly)
# ================================
try:
    sys.stdout.reconfigure(encoding='utf-8')
    sys.stderr.reconfigure(encoding='utf-8')
except AttributeError:
    import io
    sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
    sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')


def safe_print(text: str):
    enc = sys.stdout.encoding or ""
    if not enc.lower().startswith("utf"):
        text = ''.join(ch for ch in text if ord(ch) < 65536)
    try:
        print(text)
    except UnicodeEncodeError:
        text = ''.join(ch for ch in text if ord(ch) < 128)
        print(text)


# ================================
# 🔧 CONFIG
# ================================
TOKEN_PATH = Path(__file__).resolve().parent.parent / "token.txt"
CLINIC_SLUG = "mudr-buzalkova"

BATCH_SIZE = 500
STATES = ["ACTIVE", "DONE"]  # explicitně – jinak API vrací jen ACTIVE

DB_CONFIG = {
    "host": "192.168.1.76",
    "port": 3307,
    "user": "root",
    "password": "Vlado9674+",
    "database": "medevio",
    "charset": "utf8mb4",
    "cursorclass": pymysql.cursors.DictCursor,
}

GRAPHQL_QUERY = r"""
query ClinicRequestList2(
  $clinicSlug: String!,
  $queueId: String,
  $queueAssignment: QueueAssignmentFilter!,
  $state: PatientRequestState,
  $pageInfo: PageInfo!,
  $locale: Locale!
) {
  requestsResponse: listPatientRequestsForClinic2(
    clinicSlug: $clinicSlug,
    queueId: $queueId,
    queueAssignment: $queueAssignment,
    state: $state,
    pageInfo: $pageInfo
  ) {
    count
    patientRequests {
      id
      displayTitle(locale: $locale)
      createdAt
      updatedAt
      doneAt
      removedAt
      extendedPatient {
        name
        surname
        identificationNumber
      }
      lastMessage {
        createdAt
      }
    }
  }
}
"""


# ================================
# TOKEN
# ================================
def read_token(path: Path) -> str:
    tok = path.read_text(encoding="utf-8").strip()
    if tok.startswith("Bearer "):
        return tok.split(" ", 1)[1]
    return tok


# ================================
# DATETIME PARSER
# ================================
def to_mysql_dt(iso_str):
    if not iso_str:
        return None
    try:
        dt = parser.isoparse(iso_str)
        if dt.tzinfo is None:
            dt = dt.replace(tzinfo=datetime.now().astimezone().tzinfo)
        return dt.astimezone().strftime("%Y-%m-%d %H:%M:%S")
    except Exception:
        return None


# ================================
# UPSERT
# ================================
def upsert(conn, r):
    p = r.get("extendedPatient") or {}

    api_updated = to_mysql_dt(r.get("updatedAt"))
    msg_updated = to_mysql_dt((r.get("lastMessage") or {}).get("createdAt"))

    final_updated = max(filter(None, [api_updated, msg_updated]), default=None)

    sql = """
        INSERT INTO pozadavky (
            id, displayTitle, createdAt, updatedAt, doneAt, removedAt,
            pacient_jmeno, pacient_prijmeni, pacient_rodnecislo
        ) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s)
        ON DUPLICATE KEY UPDATE
            displayTitle=VALUES(displayTitle),
            updatedAt=VALUES(updatedAt),
            doneAt=VALUES(doneAt),
            removedAt=VALUES(removedAt),
            pacient_jmeno=VALUES(pacient_jmeno),
            pacient_prijmeni=VALUES(pacient_prijmeni),
            pacient_rodnecislo=VALUES(pacient_rodnecislo)
    """

    vals = (
        r.get("id"),
        r.get("displayTitle"),
        to_mysql_dt(r.get("createdAt")),
        final_updated,
        to_mysql_dt(r.get("doneAt")),
        to_mysql_dt(r.get("removedAt")),
        p.get("name"),
        p.get("surname"),
        p.get("identificationNumber"),
    )

    with conn.cursor() as cur:
        cur.execute(sql, vals)
    conn.commit()


# ================================
# FETCH PAGE (per state)
# ================================
def fetch_state(headers, state, offset):
    variables = {
        "clinicSlug": CLINIC_SLUG,
        "queueId": None,
        "queueAssignment": "ANY",
        "state": state,
        "pageInfo": {"first": BATCH_SIZE, "offset": offset},
        "locale": "cs",
    }

    payload = {
        "operationName": "ClinicRequestList2",
        "query": GRAPHQL_QUERY,
        "variables": variables,
    }

    r = requests.post("https://api.medevio.cz/graphql", json=payload, headers=headers)
    r.raise_for_status()

    data = r.json()["data"]["requestsResponse"]
    return data.get("patientRequests", []), data.get("count", 0)


# ================================
# MAIN
# ================================
def main():
    token = read_token(TOKEN_PATH)
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json",
        "Accept": "application/json",
    }

    conn = pymysql.connect(**DB_CONFIG)

    safe_print(f"\n=== FULL Medevio READ-ALL sync @ {datetime.now():%Y-%m-%d %H:%M:%S} ===")

    grand_total = 0

    for state in STATES:
        safe_print(f"\n🔁 STATE = {state}")
        offset = 0
        total = None
        processed = 0

        while True:
            batch, count = fetch_state(headers, state, offset)

            if total is None:
                total = count
                safe_print(f"📡 {state}: celkem {total}")

            if not batch:
                break

            for r in batch:
                upsert(conn, r)

            processed += len(batch)
            safe_print(f"   • {processed}/{total}")

            offset += BATCH_SIZE
            if offset >= count:
                break

            time.sleep(0.4)

        grand_total += processed

    conn.close()
    safe_print(f"\n✅ HOTOVO – celkem zpracováno {grand_total} požadavků\n")


# ================================
if __name__ == "__main__":
    main()
