#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys as _sys
_sys.stdout.reconfigure(encoding="utf-8", errors="replace")
_sys.stderr.reconfigure(encoding="utf-8", errors="replace")
"""
04_najdi_zlomy.py
=================
Pro pacienty z seznam_pojistencu_davky, kteří NEMAJÍ záznam v vzp_registrace_lekari
(skript kdojelekar je nezachytil), najde bod zlomu registrace u naší ambulance.

Algoritmus:
  1. Dotaz VZP dnes — je pacient stále registrován u nás (ICP=09305001)?
     ANO → datum_ukonceni z odpovědi = výsledek
  2. NE → hledáme rokem dozadu (od dnes, −1 rok, −2 roky …)
     dokud nenajdeme rok kdy BYL registrován → tím ohraničíme interval [lo, hi]
  3. V intervalu [lo, hi] binární hledání na den přesně
     (nebo pokud datum_ukonceni z VZP odpovědi není 3000, použijeme ho přímo)

Výsledek se uloží do tabulky seznam_pojistencu_zlomy a vytiskne na konzoli.
"""

import time
import sys
from datetime import date, timedelta
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "Knihovny"))
from mysql_db import connect_mysql
from vzpb2b_client import VZPB2BClient

# ── Konfigurace ───────────────────────────────────────────────────────────────
PFX_PATH     = str(Path(__file__).resolve().parents[1] / "Certificates" / "picka.pfx")
PFX_PASSWORD = "Vlado7309208104+"
ICZ          = "09305000"
NASA_ICP     = "09305001"
API_PAUSE    = 2          # sekundy mezi VZP dotazy

CREATE_SQL = """
CREATE TABLE IF NOT EXISTS seznam_pojistencu_zlomy (
    id            INT         NOT NULL AUTO_INCREMENT PRIMARY KEY,
    cip           VARCHAR(12) NOT NULL,
    prijmeni      VARCHAR(30) NOT NULL,
    jmeno         VARCHAR(24) NOT NULL,
    posledni_davka DATE       NOT NULL COMMENT 'Poslední měsíc kdy byl v dávce',
    zlom_datum    DATE            NULL COMMENT 'Poslední den registrace u nás (NULL=stále aktivní)',
    zlom_zdroj    VARCHAR(60)     NULL COMMENT 'Jak byl zlom určen',
    stav          VARCHAR(20) NOT NULL COMMENT 'aktivní / ukončen / nenalezen',
    dotazeno_dne  DATE        NOT NULL,
    UNIQUE KEY uq_cip (cip)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Zlomy registrace pro pacienty bez záznamu v kdojelekar';
"""

# ── VZP klient ────────────────────────────────────────────────────────────────
vzp = VZPB2BClient("prod", PFX_PATH, PFX_PASSWORD, icz=ICZ)


def je_registrovan(rc: str, k_datu: date) -> tuple[bool, date | None]:
    """
    Vrátí (registrován_u_nas: bool, datum_ukonceni: date|None).
    datum_ukonceni = None pokud nelze parsovat nebo pacient není u nás.
    """
    xml = vzp.registrace_lekare(rc, k_datu.isoformat(), odbornosti=["001"])
    time.sleep(API_PAUSE)
    try:
        zaznamy = vzp.parse_registrace_lekare(xml)
    except Exception as e:
        print(f"    [CHYBA parsování] {e}")
        return False, None

    for z in zaznamy:
        if z.get("ma_lekare") and z.get("ICP") == NASA_ICP and z.get("kod_odbornosti") == "001":
            du_str = z.get("datum_ukonceni")
            try:
                du = date.fromisoformat(du_str) if du_str else None
            except ValueError:
                du = None
            return True, du

    return False, None


def najdi_zlom(rc: str, posledni_davka: date) -> tuple[date | None, str, str]:
    """
    Vrátí (zlom_datum, zlom_zdroj, stav).
    zlom_datum = poslední den kdy byl registrován (None = stále aktivní).
    """
    today = date.today()

    # ── Krok 1: dotaz dnes ────────────────────────────────────────────────────
    print(f"  [dnes {today}]", end=" ", flush=True)
    reg, du = je_registrovan(rc, today)

    if reg:
        if du and du.year < 3000:
            print(f"registrován, ukončení {du}")
            return du, "VZP datum_ukonceni (dnes)", "ukončen"
        else:
            print("registrován, bez data ukončení → stále aktivní")
            return None, "VZP dnes aktivní", "aktivní"

    print("NENÍ registrován")

    # ── Krok 2: hledání po rocích dozadu ─────────────────────────────────────
    # lo = víme, že tam BYL (posledni_davka)
    # hi = víme, že tam NENÍ (today)
    lo: date = posledni_davka
    hi: date = today

    probe = today.replace(year=today.year - 1)
    while probe >= posledni_davka:
        print(f"  [rok {probe}]", end=" ", flush=True)
        reg_p, du_p = je_registrovan(rc, probe)
        if reg_p:
            lo = probe
            print(f"registrován")
            if du_p and du_p.year < 3000:
                print(f"  → datum_ukonceni z VZP: {du_p}")
                return du_p, f"VZP datum_ukonceni (dotaz {probe})", "ukončen"
            break
        else:
            hi = probe
            print("není")
            try:
                probe = probe.replace(year=probe.year - 1)
            except ValueError:
                break
    else:
        # Ani v posledni_davka není registrován — neobvyklé
        print(f"  ! Ani k datu {posledni_davka} není registrován — zkouším přímo")
        reg_lo, du_lo = je_registrovan(rc, posledni_davka)
        if not reg_lo:
            return None, "nenalezen ani k datu poslední dávky", "nenalezen"
        lo = posledni_davka
        if du_lo and du_lo.year < 3000:
            return du_lo, f"VZP datum_ukonceni ({posledni_davka})", "ukončen"

    # ── Krok 3: binární hledání v intervalu [lo, hi] ─────────────────────────
    print(f"  Binární hledání: {lo} … {hi}")
    iterace = 0
    while (hi - lo).days > 1:
        iterace += 1
        mid = lo + timedelta(days=(hi - lo).days // 2)
        print(f"  [{iterace}. iterace: {mid}]", end=" ", flush=True)
        reg_m, du_m = je_registrovan(rc, mid)
        if reg_m:
            lo = mid
            print("registrován")
            if du_m and du_m.year < 3000:
                print(f"  → datum_ukonceni z VZP: {du_m}")
                return du_m, f"VZP datum_ukonceni (binární {mid})", "ukončen"
        else:
            hi = mid
            print("není")

    print(f"  → Zlom: poslední den registrace = {lo}")
    return lo, f"binární hledání ({iterace} kroků)", "ukončen"


# ── Načtení pacientů ──────────────────────────────────────────────────────────

conn = connect_mysql()
cur  = conn.cursor()
cur.execute(CREATE_SQL)

# Unikátní CIP v seznamu (VZP, pojišťovna 111)
cur.execute("SELECT DISTINCT cip FROM seznam_pojistencu_davky WHERE pojistovna='111'")
vsechny_cip = {r[0] for r in cur.fetchall()}

# CIP které jsou v registrace_lekari (u nás, odb 001)
cur.execute("""
    SELECT DISTINCT rc FROM vzp_registrace_lekari
    WHERE kod_odbornosti='001' AND ICP='09305001' AND ma_lekare=1
""")
zname_cip = {r[0] for r in cur.fetchall()}

# Nespárované
nesparovane_cip = vsechny_cip - zname_cip

# Doplním jméno a posledni_davka
cur.execute("""
    SELECT cip, MIN(prijmeni), MIN(jmeno),
           MAX(DATE(CONCAT(davka_rok, '-', LPAD(davka_mesic,2,'0'), '-01')))
    FROM seznam_pojistencu_davky
    WHERE pojistovna='111'
    GROUP BY cip
""")
info = {r[0]: (r[1], r[2], r[3]) for r in cur.fetchall()}

pacienti = [
    (cip, *info[cip])
    for cip in sorted(nesparovane_cip)
    if cip in info
]

print(f"Pacientů ke zpracování: {len(pacienti)}\n")
print("=" * 70)

# ── Hlavní smyčka ─────────────────────────────────────────────────────────────

vysledky = []
for cip, prijmeni, jmeno, posledni_davka in pacienti:
    print(f"\n{prijmeni} {jmeno}  (CIP: {cip}, poslední dávka: {posledni_davka})")
    try:
        zlom, zdroj, stav = najdi_zlom(cip, posledni_davka)
    except Exception as e:
        print(f"  CHYBA: {e}")
        zlom, zdroj, stav = None, f"chyba: {e}", "chyba"

    vysledky.append((cip, prijmeni, jmeno, posledni_davka, zlom, zdroj, stav))

    cur.execute("""
        INSERT INTO seznam_pojistencu_zlomy
            (cip, prijmeni, jmeno, posledni_davka, zlom_datum, zlom_zdroj, stav, dotazeno_dne)
        VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
        ON DUPLICATE KEY UPDATE
            posledni_davka=VALUES(posledni_davka),
            zlom_datum=VALUES(zlom_datum),
            zlom_zdroj=VALUES(zlom_zdroj),
            stav=VALUES(stav),
            dotazeno_dne=VALUES(dotazeno_dne)
    """, (cip, prijmeni, jmeno, posledni_davka, zlom, zdroj, stav, date.today()))

cur.close()
conn.close()

# ── Výsledky ──────────────────────────────────────────────────────────────────
print("\n" + "=" * 70)
print(f"\n{'Příjmení':<25} {'Jméno':<20} {'CIP':<12} {'Poslední dávka':<15} {'Zlom':<12} Stav")
print("-" * 95)
for cip, pri, jme, pd, zd, zdroj, stav in vysledky:
    zlom_str = str(zd) if zd else "—"
    print(f"{pri:<25} {jme:<20} {cip:<12} {str(pd):<15} {zlom_str:<12} {stav}")
