"""
Stazeni detailu receptu (NacistPredpis) pro poslednich N receptu z Medicusu.

Spusteni:
    python 08StahnoutPredpisy.py              # 10 receptu od 2025-01-01
    python 08StahnoutPredpisy.py --limit 50   # 50 receptu
    python 08StahnoutPredpisy.py --od 2026-01-01

Pauza mezi volanimi: 5 sekund.
XML odpovedi se ukladaji do xml_archive/YYYY-MM-DD/ERP_kod.xml
"""

import sys
import time
import uuid
from datetime import datetime, timezone, date
from pathlib import Path

import fdb
from requests import Session
from requests_pkcs12 import Pkcs12Adapter

if hasattr(sys.stdout, "reconfigure"):
    sys.stdout.reconfigure(errors="replace")

# ── Konfigurace eRecept ──────────────────────────────────────────────────────
PFX_FILE   = r"C:\Users\vlado\PycharmProjects\Recepty\AMBSUKL214235369G_31DEC2024.pfx"
PFX_PASS   = "Vlado7309208104++"
API_USER   = "e08c89c6-2b1a-4eba-8ed9-4e3e63618379"
API_PASS   = "Buzalka@Vladimir2025"
UZIVATEL   = "E08C89C6-2B1A-4EBA-8ED9-4E3E63618379"
PRACOVISTE = "00214235367"
ENDPOINT   = "https://lekar-soap.erecept.sukl.cz/cuer/Lekar"
NAMESPACE  = "http://www.sukl.cz/erp/201704"

PAUZA = 5  # sekund

# ── Konfigurace Firebird ─────────────────────────────────────────────────────
FB_DSN     = r'localhost:c:\medicus 3\data\medicus.fdb'
FB_USER    = 'SYSDBA'
FB_PASS    = 'masterkey'
FB_CHARSET = 'win1250'

# ── Adresare ─────────────────────────────────────────────────────────────────
XML_DIR = Path(__file__).parent / "xml_archive"


def nacti_erp_kody(fb_conn, datum_od, limit, prijmeni=None):
    """Nacte unikatni ID_Dokladu (erp kody) z Firebirdu — recept_epodani.erp."""
    sql = """
        SELECT FIRST ? r.datum, r.lek, r.dop, r.idpac,
               TRIM(kar.prijmeni) AS prijmeni, TRIM(kar.jmeno) AS jmeno,
               ep.erp
        FROM recept r
        JOIN recept_epodani ep ON r.id_epodani = ep.id
        JOIN kar ON r.idpac = kar.idpac
        WHERE r.datum >= ? AND ep.erp IS NOT NULL
    """
    params = [limit, datum_od]
    if prijmeni:
        placeholders = ",".join(["?"] * len(prijmeni))
        sql += f" AND UPPER(TRIM(kar.prijmeni)) IN ({placeholders})"
        params.extend(p.upper() for p in prijmeni)
    sql += " ORDER BY r.datum DESC"
    cur = fb_conn.cursor()
    cur.execute(sql, params)
    rows = cur.fetchall()
    cur.close()
    # deduplikace dle erp kodu — zachovat prvni vyskyt (nejnovejsi datum)
    seen = set()
    unique = []
    for row in rows:
        erp = row[6]
        if erp not in seen:
            seen.add(erp)
            unique.append(row)
    return unique


def volej_nacist_predpis(sess, erp_kod):
    """Zavola NacistPredpis a vrati (status_code, response_text)."""
    id_zpravy = str(uuid.uuid4())
    odeslano = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S+00:00")

    soap_body = (
        '<?xml version="1.0" encoding="UTF-8"?>'
        '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">'
        '<soapenv:Body>'
        f'<NacteniPredpisuDotaz xmlns="{NAMESPACE}">'
        f'<Doklad>'
        f'<Pristupujici>'
        f'<Uzivatel>{UZIVATEL}</Uzivatel>'
        f'<Pracoviste>{PRACOVISTE}</Pracoviste>'
        f'</Pristupujici>'
        f'<Identifikator>'
        f'<ID_Dokladu>{erp_kod}</ID_Dokladu>'
        f'</Identifikator>'
        f'</Doklad>'
        f'<Zprava>'
        f'<ID_Zpravy>{id_zpravy}</ID_Zpravy>'
        f'<Verze>202501A</Verze>'
        f'<Odeslano>{odeslano}</Odeslano>'
        f'<SW_Klienta>MEDICUS_____</SW_Klienta>'
        f'</Zprava>'
        f'</NacteniPredpisuDotaz>'
        '</soapenv:Body>'
        '</soapenv:Envelope>'
    )

    headers = {
        "Content-Type": 'text/xml; charset="UTF-8"',
        "SOAPAction": '"NacistPredpis"',
        "User-Agent": "Medicus",
    }

    resp = sess.post(ENDPOINT, data=soap_body.encode("utf-8"), headers=headers, timeout=15)
    return resp.status_code, resp.text


## ── Parametry (uprav zde) ────────────────────────────────────────────────────
LIMIT      = 100                            # max pocet receptu ke stazeni
DATUM_OD   = "2025-01-01"                   # recepty od tohoto data
PRIJMENI   = ["Buzalka"]                    # filtr prijmeni (list), nebo None = vsichni
## ─────────────────────────────────────────────────────────────────────────────


def main():
    datum_od = DATUM_OD
    dnes = date.today().isoformat()
    out_dir = XML_DIR / dnes
    out_dir.mkdir(parents=True, exist_ok=True)

    # Firebird
    print(f"Pripojuji Firebird...")
    fb = fdb.connect(dsn=FB_DSN, user=FB_USER, password=FB_PASS, charset=FB_CHARSET)
    rows = nacti_erp_kody(fb, datum_od, LIMIT, PRIJMENI)
    fb.close()
    print(f"Nacteno {len(rows)} receptu z Medicusu (od {datum_od})\n")

    if not rows:
        print("Zadne recepty k stazeni.")
        return

    # SOAP session
    sess = Session()
    sess.mount("https://", Pkcs12Adapter(pkcs12_filename=PFX_FILE, pkcs12_password=PFX_PASS))
    sess.auth = (API_USER, API_PASS)

    ok = 0
    chyby = 0

    for i, row in enumerate(rows, 1):
        datum_rec, lek, dop, idpac, prijmeni, jmeno, erp_kod = row
        lek_str = f"{lek} {dop}".strip() if dop else str(lek).strip()
        label = f"{prijmeni} {jmeno}".strip()

        print(f"[{i:4d}/{len(rows)}] {label:30s} {erp_kod}  ", end="", flush=True)

        try:
            status, text = volej_nacist_predpis(sess, erp_kod)

            if status == 200 and "<soap:Fault" not in text and "Fault>" not in text:
                xml_file = out_dir / f"{erp_kod}.xml"
                xml_file.write_text(text, encoding="utf-8")
                size_kb = len(text.encode("utf-8")) / 1024
                print(f"OK  {size_kb:6.1f} KB  {lek_str[:40]}")
                ok += 1
            else:
                # SOAP Fault nebo HTTP chyba
                chyba_short = text[:120].replace("\n", " ")
                print(f"CHYBA  HTTP {status}  {chyba_short}")
                # ulozit i chybovou odpoved
                xml_file = out_dir / f"{erp_kod}_CHYBA.xml"
                xml_file.write_text(text, encoding="utf-8")
                chyby += 1

        except Exception as e:
            print(f"EXCEPTION  {e}")
            chyby += 1

        if i < len(rows):
            time.sleep(PAUZA)

    print(f"\nHotovo: {ok} OK, {chyby} chyb")
    print(f"XML: {out_dir}")


if __name__ == "__main__":
    main()
