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

"""
Stáhne konverzaci pro požadavky, kde:
messagesProcessed IS NULL OR messagesProcessed < updatedAt.

Vloží do medevio_conversation a přílohy do medevio_downloads.
"""

import zlib
import json
import requests
import pymysql
from pathlib import Path
from datetime import datetime
import time
import sys

# Force UTF-8 output even under Windows Task Scheduler
import sys
try:
    sys.stdout.reconfigure(encoding='utf-8')
    sys.stderr.reconfigure(encoding='utf-8')
except AttributeError:
    # Python < 3.7 fallback (not needed for you, but safe)
    import io
    sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
    sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')

# ==============================
# 🛡 SAFE PRINT FOR CP1250 / EMOJI
# ==============================
def safe_print(text: str):
    enc = sys.stdout.encoding or ""
    if not enc or not enc.lower().startswith("utf"):
        # strip emoji + characters outside BMP for Task Scheduler (CP1250)
        text = ''.join(ch for ch in text if ord(ch) < 65536)
    try:
        print(text)
    except UnicodeEncodeError:
        # fallback pure ASCII
        text = ''.join(ch for ch in text if ord(ch) < 128)
        print(text)


# ==============================
# 🔧 CONFIGURATION
# ==============================
TOKEN_PATH = Path(__file__).resolve().parent.parent / "token.txt"

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

GRAPHQL_QUERY_MESSAGES = r"""
query UseMessages_ListMessages($requestId: String!, $updatedSince: DateTime) {
  messages: listMessages(patientRequestId: $requestId, updatedSince: $updatedSince) {
    id
    createdAt
    updatedAt
    readAt
    text
    type
    sender {
      id
      name
      surname
      clinicId
    }
    medicalRecord {
      id
      description
      contentType
      url
      downloadUrl
      token
      createdAt
      updatedAt
    }
  }
}
"""

# ==============================
# ⏱ DATETIME PARSER
# ==============================
def parse_dt(s):
    if not s:
        return None
    try:
        return datetime.fromisoformat(s.replace("Z", "+00:00"))
    except:
        pass
    try:
        return datetime.strptime(s[:19], "%Y-%m-%dT%H:%M:%S")
    except:
        return None

# ==============================
# 🔐 TOKEN
# ==============================
def read_token(path: Path) -> str:
    tok = path.read_text(encoding="utf-8").strip()
    return tok.replace("Bearer ", "")

# ==============================
# 📡 FETCH MESSAGES
# ==============================
def fetch_messages(headers, request_id):
    payload = {
        "operationName": "UseMessages_ListMessages",
        "query": GRAPHQL_QUERY_MESSAGES,
        "variables": {"requestId": request_id, "updatedSince": None},
    }

    r = requests.post("https://api.medevio.cz/graphql", json=payload, headers=headers, timeout=30)
    if r.status_code != 200:
        safe_print(f"❌ HTTP {r.status_code} for request {request_id}")
        return []
    return r.json().get("data", {}).get("messages", []) or []


# ==============================
# 💾 SAVE MESSAGE
# ==============================
def insert_message(cur, req_id, msg):

    sender = msg.get("sender") or {}
    sender_name = " ".join(
        x for x in [sender.get("name"), sender.get("surname")] if x
    ) or None

    sql = """
    INSERT INTO medevio_conversation (
        id, request_id,
        sender_name, sender_id, sender_clinic_id,
        text, created_at, read_at, updated_at,
        attachment_url, attachment_description, attachment_content_type
    ) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)
    ON DUPLICATE KEY UPDATE
        sender_name = VALUES(sender_name),
        sender_id = VALUES(sender_id),
        sender_clinic_id = VALUES(sender_clinic_id),
        text = VALUES(text),
        created_at = VALUES(created_at),
        read_at = VALUES(read_at),
        updated_at = VALUES(updated_at),
        attachment_url = VALUES(attachment_url),
        attachment_description = VALUES(attachment_description),
        attachment_content_type = VALUES(attachment_content_type)
    """

    mr = msg.get("medicalRecord") or {}

    cur.execute(sql, (
        msg.get("id"),
        req_id,
        sender_name,
        sender.get("id"),
        sender.get("clinicId"),
        msg.get("text"),
        parse_dt(msg.get("createdAt")),
        parse_dt(msg.get("readAt")),
        parse_dt(msg.get("updatedAt")),
        mr.get("downloadUrl") or mr.get("url"),
        mr.get("description"),
        mr.get("contentType")
    ))


# ==============================
# 💾 DOWNLOAD MESSAGE ATTACHMENT
# ==============================
def insert_download(cur, req_id, msg, existing_ids):

    mr = msg.get("medicalRecord") or {}
    attachment_id = mr.get("id")
    if not attachment_id:
        return

    if attachment_id in existing_ids:
        return

    url = mr.get("downloadUrl") or mr.get("url")
    if not url:
        return

    try:
        r = requests.get(url, timeout=30)
        r.raise_for_status()
        data = r.content
    except Exception as e:
        safe_print(f"⚠️ Failed to download: {e}")
        return

    filename = url.split("/")[-1].split("?")[0]

    cur.execute("""
        INSERT INTO medevio_downloads (
            request_id, attachment_id, attachment_type,
            filename, content_type, file_size, created_at, file_content
        ) VALUES (%s,%s,%s,%s,%s,%s,%s,%s)
        ON DUPLICATE KEY UPDATE
            file_content = VALUES(file_content),
            file_size = VALUES(file_size),
            downloaded_at = NOW()
    """, (
        req_id,
        attachment_id,
        "MESSAGE_ATTACHMENT",
        filename,
        mr.get("contentType"),
        len(data),
        parse_dt(msg.get("createdAt")),
        data
    ))

    existing_ids.add(attachment_id)


# ==============================
# 🧠 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)

    # ---- Load existing attachments
    with conn.cursor() as cur:
        cur.execute("SELECT attachment_id FROM medevio_downloads")
        existing_ids = {row["attachment_id"] for row in cur.fetchall()}

    safe_print(f"📦 Already downloaded attachments: {len(existing_ids)}\n")

    # ---- Select pozadavky needing message sync
    sql = """
        SELECT id
        FROM pozadavky
        WHERE messagesProcessed IS NULL
           OR messagesProcessed < updatedAt
    """
    with conn.cursor() as cur:
        cur.execute(sql)
        requests_to_process = cur.fetchall()

    safe_print(f"📋 Found {len(requests_to_process)} pozadavků requiring message sync.\n")

    # ---- Process each record
    for idx, row in enumerate(requests_to_process, 1):
        req_id = row["id"]
        safe_print(f"[{idx}/{len(requests_to_process)}] Processing {req_id} …")

        messages = fetch_messages(headers, req_id)

        with conn.cursor() as cur:
            for msg in messages:
                insert_message(cur, req_id, msg)
                insert_download(cur, req_id, msg, existing_ids)
            conn.commit()

        with conn.cursor() as cur:
            cur.execute("UPDATE pozadavky SET messagesProcessed = NOW() WHERE id = %s", (req_id,))
            conn.commit()

        safe_print(f"   ✅ {len(messages)} messages saved\n")
        time.sleep(0.25)

    conn.close()
    safe_print("🎉 Done!")


if __name__ == "__main__":
    main()
