#!/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")
"""
05_report_excel.py
==================
Kompletní Excel report všech VZP pojištěnců z dávek.
Kombinuje čtyři zdroje:
  - seznam_pojistencu_davky        → první/poslední dávka, zda v aktuální
  - vzp_registrace_lekari          → datum_ukonceni od VZP (989 pacientů)
  - seznam_pojistencu_zlomy        → bod zlomu pro 13 nespárovaných
  - seznam_pojistencu_nasledny_lekar → nový lékař / nenalezen po ukončení

Listy:
  1. Všichni pojištěnci   – kompletní přehled, řazeno příjmení
  2. Aktivní              – stále registrováni
  3. Ukončení             – registrace ukončena + nový lékař / osud
  4. Nenalezeni           – bez dostatečných dat
"""

import sys
from datetime import date
from pathlib import Path

import openpyxl
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from openpyxl.utils import get_column_letter

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

TODAY   = date.today()
OUTPUT  = Path(__file__).parent / "report_pojistenci.xlsx"

# ── Barvy ─────────────────────────────────────────────────────────────────────
C_HDR_DARK   = "1F4E79"
C_HDR_MED    = "2E75B6"
C_AKTIVNI    = "E2EFDA"   # zelená
C_UKONCEN    = "FCE4D6"   # lososová
C_NENALEZEN  = "FFF2CC"   # žlutá
C_ZEBRA      = "F2F2F2"
C_TITLE_AKT  = "375623"
C_TITLE_UKO  = "C55A11"
C_TITLE_NEN  = "7F6000"

THIN = Side(style="thin", color="BFBFBF")

def border():
    return Border(left=THIN, right=THIN, top=THIN, bottom=THIN)

def hdr(cell, text, bg=C_HDR_DARK, fg="FFFFFF", size=10):
    cell.value = text
    cell.font  = Font(bold=True, color=fg, size=size)
    cell.fill  = PatternFill("solid", fgColor=bg)
    cell.alignment = Alignment(horizontal="center", vertical="center", wrap_text=True)
    cell.border = border()

def cell(ws, row, col, value, bg=None, bold=False, align="left", fmt=None, color="000000"):
    c = ws.cell(row, col, value)
    c.font      = Font(bold=bold, size=10, color=color)
    c.alignment = Alignment(horizontal=align, vertical="center")
    c.border    = border()
    if bg:
        c.fill = PatternFill("solid", fgColor=bg)
    if fmt:
        c.number_format = fmt
    return c

def title_row(ws, row, text, ncols, bg, fg="FFFFFF", height=26):
    ws.merge_cells(start_row=row, start_column=1, end_row=row, end_column=ncols)
    c = ws.cell(row, 1)
    c.value = text
    c.font  = Font(bold=True, size=13, color=fg)
    c.fill  = PatternFill("solid", fgColor=bg)
    c.alignment = Alignment(horizontal="center", vertical="center")
    ws.row_dimensions[row].height = height

def autofit(ws, widths):
    for i, w in enumerate(widths, 1):
        ws.column_dimensions[get_column_letter(i)].width = w

# ── Načtení dat ───────────────────────────────────────────────────────────────
print("Načítám data z DB ...")
conn = connect_mysql()
cur  = conn.cursor()

# 1. Ze seznam_pojistencu_davky: rozsah přítomnosti + počet dávek
cur.execute("""
    SELECT
        cip,
        MIN(prijmeni)  AS prijmeni,
        MIN(jmeno)     AS jmeno,
        MIN(DATE(CONCAT(davka_rok,'-',LPAD(davka_mesic,2,'0'),'-',LPAD(davka_den,2,'0')))) AS prvni_davka,
        MAX(DATE(CONCAT(davka_rok,'-',LPAD(davka_mesic,2,'0'),'-',LPAD(davka_den,2,'0')))) AS posledni_davka,
        COUNT(DISTINCT CONCAT(davka_rok,davka_mesic))                  AS pocet_davek
    FROM seznam_pojistencu_davky
    WHERE pojistovna='111'
    GROUP BY cip
""")
seznam = {r[0]: {"prijmeni": r[1], "jmeno": r[2],
                 "prvni": r[3], "posledni": r[4], "pocet_davek": r[5]}
          for r in cur.fetchall()}

# Nejnovější datum dávky (pro sloupec "v aktuální dávce")
cur.execute("""
    SELECT MAX(DATE(CONCAT(davka_rok,'-',LPAD(davka_mesic,2,'0'),'-',LPAD(davka_den,2,'0'))))
    FROM seznam_pojistencu_davky WHERE pojistovna='111'
""")
nejnovejsi_davka = cur.fetchone()[0]

cur.execute("""
    SELECT DISTINCT cip FROM seznam_pojistencu_davky
    WHERE pojistovna='111'
      AND CONCAT(davka_rok,LPAD(davka_mesic,2,'0'),LPAD(davka_den,2,'0')) = (
          SELECT MAX(CONCAT(davka_rok,LPAD(davka_mesic,2,'0'),LPAD(davka_den,2,'0')))
          FROM seznam_pojistencu_davky WHERE pojistovna='111'
      )
""")
v_aktualni = {r[0] for r in cur.fetchall()}

# 2. Z vzp_registrace_lekari: nejnovější záznam na pacienta (u nás, odb 001)
cur.execute("""
    SELECT r.rc, r.datum_zahajeni, r.datum_ukonceni, r.k_datu
    FROM vzp_registrace_lekari r
    INNER JOIN (
        SELECT rc, MAX(k_datu) AS max_k
        FROM vzp_registrace_lekari
        WHERE kod_odbornosti='001' AND ICP='09305001' AND ma_lekare=1
        GROUP BY rc
    ) latest ON r.rc = latest.rc AND r.k_datu = latest.max_k
    WHERE r.kod_odbornosti='001' AND r.ICP='09305001' AND r.ma_lekare=1
""")
registrace = {r[0]: {"zahajeni": r[1], "ukonceni": r[2], "k_datu": r[3]}
              for r in cur.fetchall()}

# 3. Ze seznam_pojistencu_zlomy (13 nespárovaných)
cur.execute("SELECT cip, zlom_datum, zlom_zdroj, stav FROM seznam_pojistencu_zlomy")
zlomy = {r[0]: {"ukonceni": r[1], "zdroj": r[2], "stav": r[3]}
         for r in cur.fetchall()}

# 4. Následný lékař po ukončení
cur.execute("""
    SELECT cip, stav_vzp, novy_nazev, novy_ordinace, novy_icp, datum_prehlaseni
    FROM seznam_pojistencu_nasledny_lekar
""")
nasledni = {r[0]: {"stav_vzp": r[1], "novy_nazev": r[2],
                    "novy_ordinace": r[3], "novy_icp": r[4],
                    "datum_prehlaseni": r[5]}
            for r in cur.fetchall()}

cur.close()
conn.close()

# ── Sestavení řádků ───────────────────────────────────────────────────────────
print(f"Pacientů celkem: {len(seznam)}")

radky = []
for cip, s in seznam.items():
    v_akt = cip in v_aktualni

    if cip in registrace:
        reg   = registrace[cip]
        du    = reg["ukonceni"]
        zdroj = f"vzp_registrace ({reg['k_datu']})"
    elif cip in zlomy:
        z     = zlomy[cip]
        du    = z["ukonceni"]
        zdroj = z["zdroj"]
    else:
        du    = None
        zdroj = "—"

    if du is None:
        stav = "aktivní"
    elif du.year >= 3000:
        stav = "aktivní"
        du   = None   # nezobrazujeme 3000-01-01
    elif du >= TODAY:
        stav = "aktivní"
    else:
        stav = "ukončen"

    if zdroj == "—" and not v_akt:
        stav = "nenalezen"

    # Následný lékař
    nl = nasledni.get(cip)
    if nl:
        po_ukonceni  = nl["stav_vzp"]   # prehlasil / nenalezen / bez_lekare
        novy_lekar   = nl["novy_nazev"] or nl["novy_ordinace"] or ""
        if nl["novy_icp"]:
            novy_lekar += f" (ICP {nl['novy_icp']})"
        datum_prehl  = nl["datum_prehlaseni"]
    else:
        po_ukonceni = ""
        novy_lekar  = ""
        datum_prehl = None

    radky.append({
        "cip":          cip,
        "prijmeni":     s["prijmeni"],
        "jmeno":        s["jmeno"],
        "prvni":        s["prvni"],
        "posledni":     s["posledni"],
        "pocet_davek":  s["pocet_davek"],
        "v_aktualni":   v_akt,
        "ukonceni":     du,
        "zdroj":        zdroj,
        "stav":         stav,
        "po_ukonceni":  po_ukonceni,
        "novy_lekar":   novy_lekar,
        "datum_prehl":  datum_prehl,
    })

DATUM_REGISTRACE_OD = date(2025, 1, 1)

radky.sort(key=lambda r: (r["prijmeni"], r["jmeno"]))

aktivni    = [r for r in radky if r["stav"] == "aktivní"]
ukonceni   = sorted([r for r in radky if r["stav"] == "ukončen"],
                    key=lambda r: r["ukonceni"] or date.min)
nenalezeni = [r for r in radky if r["stav"] == "nenalezen"]
# Noví: datum_zahajeni registrace u nás >= 01.01.2025, řazeno chronologicky
novi = sorted(
    [r for r in radky
     if registrace.get(r["cip"], {}).get("zahajeni") is not None
     and registrace[r["cip"]]["zahajeni"] >= DATUM_REGISTRACE_OD],
    key=lambda r: (registrace[r["cip"]]["zahajeni"], r["prijmeni"], r["jmeno"])
)

print(f"  Aktivní:    {len(aktivni)}")
print(f"  Ukončení:   {len(ukonceni)}")
print(f"  Noví:       {len(novi)}")
print(f"  Nenalezeni: {len(nenalezeni)}")

# ── Excel ─────────────────────────────────────────────────────────────────────
SLOUPCE_ALL = ["Příjmení", "Jméno", "ČIP", "První\ndávka", "Poslední\ndávka",
               "Počet\ndávek", "V aktuální\ndávce", "Ukončení\nregistrace",
               "Stav", "Po ukončení", "Nový lékař / poznámka", "Datum\npřehlášení"]
WIDTHS_ALL  = [24, 18, 13, 12, 13, 9, 10, 14, 10, 13, 40, 13]

SLOUPCE = SLOUPCE_ALL  # alias pro funkci zapsat_list
WIDTHS  = WIDTHS_ALL
NCOLS   = len(SLOUPCE)
DATE_FMT = "DD.MM.YYYY"

def zapsat_list(ws, nadpis, bg_title, seznam_radku, stav_bg):
    ws.freeze_panes = "A3"
    title_row(ws, 1, nadpis, NCOLS, bg_title)
    ws.row_dimensions[2].height = 30
    for col, h in enumerate(SLOUPCE, 1):
        hdr(ws.cell(2, col), h)
    autofit(ws, WIDTHS)

    PO_CLR = {"prehlasil": "375623", "nenalezen": "C55A11",
              "bez_lekare": "7F6000", "": "000000"}
    PO_TXT = {"prehlasil": "přehlásil se", "nenalezen": "nenalezen",
              "bez_lekare": "bez lékaře",   "": ""}

    for ri, r in enumerate(seznam_radku, 3):
        bg = stav_bg if ri % 2 == 0 else None
        cell(ws, ri, 1,  r["prijmeni"],    bg)
        cell(ws, ri, 2,  r["jmeno"],       bg)
        cell(ws, ri, 3,  r["cip"],         bg, align="center")
        cell(ws, ri, 4,  r["prvni"],       bg, align="center", fmt=DATE_FMT)
        cell(ws, ri, 5,  r["posledni"],    bg, align="center", fmt=DATE_FMT)
        cell(ws, ri, 6,  r["pocet_davek"], bg, align="right")
        akt_txt = "✓" if r["v_aktualni"] else "–"
        akt_clr = "375623" if r["v_aktualni"] else "C55A11"
        cell(ws, ri, 7,  akt_txt,          bg, bold=True, align="center", color=akt_clr)
        cell(ws, ri, 8,  r["ukonceni"],    bg, align="center", fmt=DATE_FMT)
        cell(ws, ri, 9,  r["stav"],        bg, align="center", bold=True,
             color=("375623" if r["stav"]=="aktivní" else
                    "C55A11" if r["stav"]=="ukončen" else "7F6000"))
        po  = r.get("po_ukonceni", "")
        cell(ws, ri, 10, PO_TXT.get(po, po), bg, align="center", bold=bool(po),
             color=PO_CLR.get(po, "000000"))
        cell(ws, ri, 11, r.get("novy_lekar", ""),  bg)
        cell(ws, ri, 12, r.get("datum_prehl"),      bg, align="center", fmt=DATE_FMT)

C_REGISTRACE  = "DAEEF3"   # světle modrá
C_TITLE_REG   = "17375E"

SLOUPCE_REG = ["Příjmení", "Jméno", "ČIP", "Zahájení\nregistrace",
               "Ukončení\nregistrace", "Počet\ndávek", "V aktuální\ndávce",
               "Stav", "Po ukončení", "Nový lékař / poznámka", "Datum\npřehlášení"]
WIDTHS_REG  = [24, 18, 13, 16, 14, 9, 10, 10, 13, 40, 13]

PO_CLR_REG = {"prehlasil": "375623", "nenalezen": "C55A11",
              "bez_lekare": "7F6000", "": "000000"}
PO_TXT_REG = {"prehlasil": "přehlásil se", "nenalezen": "nenalezen",
              "bez_lekare": "bez lékaře",   "": ""}

def zapsat_registrace(ws, nadpis, seznam_radku):
    ncols = len(SLOUPCE_REG)
    ws.freeze_panes = "A3"
    title_row(ws, 1, nadpis, ncols, C_TITLE_REG)
    ws.row_dimensions[2].height = 30
    for col, h in enumerate(SLOUPCE_REG, 1):
        hdr(ws.cell(2, col), h, bg=C_TITLE_REG)
    autofit(ws, WIDTHS_REG)

    for ri, r in enumerate(seznam_radku, 3):
        bg = C_REGISTRACE if ri % 2 == 0 else None
        cell(ws, ri, 1, r["prijmeni"],   bg)
        cell(ws, ri, 2, r["jmeno"],      bg)
        cell(ws, ri, 3, r["cip"],        bg, align="center")
        zahajeni = registrace.get(r["cip"], {}).get("zahajeni")
        cell(ws, ri, 4, zahajeni,        bg, align="center", fmt=DATE_FMT)
        cell(ws, ri, 5, r["ukonceni"],   bg, align="center", fmt=DATE_FMT)
        cell(ws, ri, 6, r["pocet_davek"],bg, align="right")
        akt_txt = "✓" if r["v_aktualni"] else "–"
        akt_clr = "375623" if r["v_aktualni"] else "C55A11"
        cell(ws, ri, 7, akt_txt,         bg, bold=True, align="center", color=akt_clr)
        cell(ws, ri, 8, r["stav"],       bg, align="center", bold=True,
             color=("375623" if r["stav"] == "aktivní" else "C55A11"))
        po = r.get("po_ukonceni", "")
        cell(ws, ri, 9,  PO_TXT_REG.get(po, po), bg, align="center", bold=bool(po),
             color=PO_CLR_REG.get(po, "000000"))
        cell(ws, ri, 10, r.get("novy_lekar", ""),  bg)
        cell(ws, ri, 11, r.get("datum_prehl"),      bg, align="center", fmt=DATE_FMT)

wb = openpyxl.Workbook()

# List 1 – Všichni
ws1 = wb.active
ws1.title = "Všichni pojištěnci"
zapsat_list(ws1,
    f"VZP pojištěnci — kompletní přehled  ({TODAY.strftime('%d.%m.%Y')})  |  "
    f"celkem: {len(radky)}  |  aktivní: {len(aktivni)}  |  ukončení: {len(ukonceni)}",
    C_HDR_DARK, radky, C_ZEBRA)

# List 2 – Aktivní
ws2 = wb.create_sheet("Aktivní")
zapsat_list(ws2,
    f"Aktivní pojištěnci  ({TODAY.strftime('%d.%m.%Y')})  —  celkem: {len(aktivni)}",
    C_TITLE_AKT, aktivni, C_AKTIVNI)

# List 3 – Ukončení
ws3 = wb.create_sheet("Ukončení")
zapsat_list(ws3,
    f"Ukončená registrace  —  celkem: {len(ukonceni)}",
    C_TITLE_UKO, ukonceni, C_UKONCEN)

# List 4 – Registrace (noví po 31.12.2024)
ws4 = wb.create_sheet("Registrace")
zapsat_registrace(ws4,
    f"Noví pojištěnci — datum zahájení registrace od 1.1.2025  —  celkem: {len(novi)}",
    novi)

# List 5 – Nenalezeni
if nenalezeni:
    ws5 = wb.create_sheet("Nenalezeni")
    zapsat_list(ws5,
        f"Bez dostatečných dat  —  celkem: {len(nenalezeni)}",
        C_TITLE_NEN, nenalezeni, C_NENALEZEN)

wb.save(OUTPUT)
print(f"\nExcel uložen: {OUTPUT}")
