"""
Export prehledu lekoveho zaznamu pacienta do Excelu.

Nastaveni:
  RODNE_CISLO  ... rodne cislo pacienta (s lomitkem i bez)
  DATUM_OD     ... predpisy od tohoto data ve formatu DD.MM.RRRR (None = vsechny)
  VYSTUP_DIR   ... slozka kam se ulozi Excel (None = stejna slozka jako skript)
"""

from datetime import datetime
from pathlib import Path
import sys
import fdb
import pymysql
import pymysql.cursors
from openpyxl import Workbook
from openpyxl.styles import (Font, PatternFill, Alignment, Border, Side,
                              GradientFill)
from openpyxl.utils import get_column_letter



def odbornost_z_icp(icp):
    """Vrati nazev odbornosti podle ICP (plny 8-znakovy kod) z tabulky vzp_pracoviste."""
    if not icp:
        return ""
    return ODBORNOST.get(icp, f"odb. {icp[-3:]}")


# ── NASTAVENÍ ─────────────────────────────────────────────────────────────────
RODNE_CISLO = "370315041"
DATUM_OD    = "01.01.2025"   # None = vsechny predpisy
VYSTUP_DIR  = None           # None = stejny adresar jako skript
# ─────────────────────────────────────────────────────────────────────────────

FB = dict(
    dsn      = r"localhost:c:\medicus 3\data\medicus.fdb",
    user     = "SYSDBA",
    password = "masterkey",
    charset  = "win1250",
)



DB = dict(
    host        = "192.168.1.76",
    user        = "root",
    password    = "Vlado9674+",
    database    = "medicus",
    charset     = "utf8mb4",
    cursorclass = pymysql.cursors.DictCursor,
)
def _nacti_odbornosti():
    """Nacteni odbornosti z MySQL: vzp_pracoviste JOIN odbornost (aktualne platne ICP)."""
    conn = pymysql.connect(**DB)
    try:
        with conn.cursor(pymysql.cursors.Cursor) as cur:
            cur.execute("""
                SELECT vp.icp, o.nazev
                FROM vzp_pracoviste vp
                JOIN odbornost o ON o.kod = vp.odbornost
                WHERE CURDATE() BETWEEN vp.platnost_od AND vp.platnost_do
                ORDER BY vp.platnost_od DESC
            """)
            result = {}
            for icp, nazev in cur.fetchall():
                result.setdefault(icp, nazev)
            return result
    finally:
        conn.close()

ODBORNOST = _nacti_odbornosti()



# ── Barvy ─────────────────────────────────────────────────────────────────────
C_HEADER_BG   = "1F4E79"   # tmave modra — hlavicka tabulky
C_HEADER_FG   = "FFFFFF"   # bila — text hlavicky
C_TITLE_BG    = "2E75B6"   # stredni modra — nadpis sekce
C_TITLE_FG    = "FFFFFF"
C_INFO_BG     = "DEEAF1"   # svetle modra — info o pacientovi
C_ROW_ODD     = "FFFFFF"   # bila
C_ROW_EVEN    = "EBF3FB"   # velmi svetle modra — striped
C_NEVYZV_BG   = "FCE4D6"   # lososova — nevyzvednuto
C_BORDER      = "B8CCE4"


def thin_border():
    s = Side(style="thin", color=C_BORDER)
    return Border(left=s, right=s, top=s, bottom=s)


def header_fill(color):
    return PatternFill("solid", fgColor=color)


def parse_datum(s, nazev):
    try:
        return datetime.strptime(s, "%d.%m.%Y").date()
    except (ValueError, TypeError):
        sys.exit(f"Spatny format data '{nazev}': '{s}'")


def najdi_v_firebirdu(rc):
    rc = rc.replace("/", "").replace(" ", "")
    conn = fdb.connect(**FB)
    try:
        cur = conn.cursor()
        cur.execute("SELECT KAR.PRIJMENI, KAR.JMENO, KAR.DATNAR FROM KAR WHERE KAR.RODCIS = ?", (rc,))
        row = cur.fetchone()
        if not row:
            sys.exit(f"Rodne cislo '{rc}' nenalezeno v Medicusu.")
        return {"prijmeni": row[0].strip(), "jmeno": row[1].strip(), "datnar": row[2]}
    finally:
        conn.close()


def nacti_data(prijmeni, datum_narozeni, datum_od):
    conn = pymysql.connect(**DB)
    try:
        with conn.cursor() as cur:
            cur.execute(
                "SELECT id, prijmeni, jmena, datum_narozeni FROM pacient "
                "WHERE prijmeni = %s AND datum_narozeni = %s",
                (prijmeni, datum_narozeni)
            )
            pac = cur.fetchone()
            if not pac:
                sys.exit(f"Pacient '{prijmeni}' nar. {datum_narozeni} nema zaznam v MySQL.")

            # Lekari
            cur.execute("""
                SELECT pr.prijmeni, pr.jmena,
                       pr.icp,
                       pr.pzs_nazev, pr.ulice, pr.psc, pr.mesto,
                       COUNT(*) AS pocet
                FROM zprava z
                JOIN predpis p        ON p.zprava_id    = z.id
                JOIN predepisujici pr ON pr.lekar_kod   = p.kod_predepisujiciho
                WHERE z.pacient_id = %s
                GROUP BY pr.lekar_kod, pr.prijmeni, pr.jmena, pr.icp,
                         pr.pzs_nazev, pr.ulice, pr.psc, pr.mesto
                ORDER BY pocet DESC
            """, (pac["id"],))
            lekari = cur.fetchall()

            # Predpisy
            podminka = "AND p.datum_vystaveni >= %s" if datum_od else ""
            params   = (pac["id"], datum_od) if datum_od else (pac["id"],)
            cur.execute(f"""
                SELECT p.datum_vystaveni,
                       COALESCE(v.nazev, p.nazev) AS vydany_lek,
                       v.nazev IS NULL             AS nevyzvednuto,
                       p.atc, p.navod,
                       pr.prijmeni AS lek_prijmeni, pr.jmena AS lek_jmena,
                       pr.icp,
                       pr.pzs_nazev, pr.ulice, pr.psc, pr.mesto
                FROM zprava z
                JOIN predpis p        ON p.zprava_id    = z.id
                JOIN predepisujici pr ON pr.lekar_kod   = p.kod_predepisujiciho
                LEFT JOIN vydej v     ON v.id_lp_predpis = p.id_lp_predpis
                WHERE z.pacient_id = %s {podminka}
                ORDER BY p.datum_vystaveni DESC
            """, params)
            predpisy = cur.fetchall()

        return pac, lekari, predpisy
    finally:
        conn.close()


def nastav_sirky(ws, sirky):
    for col, width in sirky.items():
        ws.column_dimensions[col].width = width


def autofit(ws, min_width=5, max_width=60, padding=2):
    """Autofit sloupcu a radku podle obsahu."""
    col_widths = {}
    for row in ws.iter_rows():
        for cell in row:
            if cell.value is None:
                continue
            # Preskoc mergnuté bunky — jejich sirka se pocita ze zakladni bunky
            if isinstance(cell, type(cell)) and hasattr(cell, 'column'):
                text = str(cell.value)
                # Tučný text je trochu širší
                factor = 1.15 if (cell.font and cell.font.bold) else 1.0
                width  = len(text) * factor + padding
                col    = get_column_letter(cell.column)
                col_widths[col] = max(col_widths.get(col, min_width), width)

    for col, width in col_widths.items():
        ws.column_dimensions[col].width = min(max(width, min_width), max_width)

    # Autofit výšky řádků (wrap_text obsah)
    for row in ws.iter_rows():
        max_lines = 1
        for cell in row:
            if cell.value and cell.alignment and cell.alignment.wrap_text:
                col_w = ws.column_dimensions[get_column_letter(cell.column)].width or 10
                lines = max(1, int(len(str(cell.value)) / max(col_w, 1)) + 1)
                max_lines = max(max_lines, lines)
        row_num = row[0].row
        if max_lines > 1:
            ws.row_dimensions[row_num].height = max(ws.row_dimensions[row_num].height or 15,
                                                    max_lines * 14)


def zapis_nadpis_sekce(ws, row, text, n_cols):
    ws.merge_cells(start_row=row, start_column=1, end_row=row, end_column=n_cols)
    cell = ws.cell(row=row, column=1, value=text)
    cell.font      = Font(name="Arial", bold=True, size=11, color=C_TITLE_FG)
    cell.fill      = header_fill(C_TITLE_BG)
    cell.alignment = Alignment(horizontal="left", vertical="center", indent=1)
    ws.row_dimensions[row].height = 20
    return row + 1


def zapis_hlavicku(ws, row, hlavicka, n_cols=None):
    for col, text in enumerate(hlavicka, 1):
        cell = ws.cell(row=row, column=col, value=text)
        cell.font      = Font(name="Arial", bold=True, size=10, color=C_HEADER_FG)
        cell.fill      = header_fill(C_HEADER_BG)
        cell.alignment = Alignment(horizontal="center", vertical="center", wrap_text=True)
        cell.border    = thin_border()
    ws.row_dimensions[row].height = 28
    return row + 1


def zapis_radek(ws, row, hodnoty, highlight=False):
    bg = C_NEVYZV_BG if highlight else (C_ROW_EVEN if row % 2 == 0 else C_ROW_ODD)
    fill = header_fill(bg)
    for col, val in enumerate(hodnoty, 1):
        cell = ws.cell(row=row, column=col, value=val)
        cell.font      = Font(name="Arial", size=10)
        cell.fill      = fill
        cell.alignment = Alignment(vertical="center", wrap_text=True)
        cell.border    = thin_border()
    ws.row_dimensions[row].height = 18
    return row + 1


def vytvor_excel(pac, lekari, predpisy, datum_od, fb_pac):
    wb = Workbook()
    ws = wb.active
    ws.title = "Lekovy zaznam"

    # ── Záhlaví — info o pacientovi ──────────────────────────────────────────
    n_cols = 8
    ws.merge_cells(start_row=1, start_column=1, end_row=1, end_column=n_cols)
    title_cell = ws.cell(row=1, column=1,
        value=f"LÉKOVÝ ZÁZNAM  —  {pac['prijmeni'].upper()} {fb_pac['jmeno'].upper()}")
    title_cell.font      = Font(name="Arial", bold=True, size=14, color=C_HEADER_FG)
    title_cell.fill      = header_fill(C_HEADER_BG)
    title_cell.alignment = Alignment(horizontal="left", vertical="center", indent=1)
    ws.row_dimensions[1].height = 32

    info = [
        ("Datum narození:", pac["datum_narozeni"].strftime("%d.%m.%Y")),
        ("Datum tisku:",    datetime.today().strftime("%d.%m.%Y")),
        ("Předpisy od:",    datum_od.strftime("%d.%m.%Y") if datum_od else "vše"),
    ]
    for i, (label, val) in enumerate(info, 2):
        ws.merge_cells(start_row=i, start_column=1, end_row=i, end_column=2)
        ws.merge_cells(start_row=i, start_column=3, end_row=i, end_column=n_cols)
        lbl = ws.cell(row=i, column=1, value=label)
        lbl.font      = Font(name="Arial", bold=True, size=10)
        lbl.fill      = header_fill(C_INFO_BG)
        lbl.alignment = Alignment(vertical="center", indent=1)
        val_cell = ws.cell(row=i, column=3, value=val)
        val_cell.font      = Font(name="Arial", size=10)
        val_cell.fill      = header_fill(C_INFO_BG)
        val_cell.alignment = Alignment(vertical="center")
        ws.row_dimensions[i].height = 16

    row = len(info) + 3  # prázdný řádek

    # ── Tabulka lékařů ───────────────────────────────────────────────────────
    row = zapis_nadpis_sekce(ws, row, "PŘEDEPISUJÍCÍ LÉKAŘI", n_cols)
    row = zapis_hlavicku(ws, row, ["#", "Lékař", "Odbornost", "Pracoviště", "Ulice", "PSČ", "Město", "Předpisů"])
    for i, r in enumerate(lekari, 1):
        adresa_ulice = r.get("ulice") or ""
        row = zapis_radek(ws, row, [
            i,
            f"{r['prijmeni']} {r['jmena']}",
            odbornost_z_icp(r.get("icp")),
            r.get("pzs_nazev") or "",
            adresa_ulice,
            r.get("psc") or "",
            r.get("mesto") or "",
            r["pocet"],
        ])

    row += 1  # prázdný řádek

    # ── Tabulka předpisů ─────────────────────────────────────────────────────
    od_text = datum_od.strftime("%d.%m.%Y") if datum_od else "vše"
    row = zapis_nadpis_sekce(ws, row, f"VŠECHNY PŘEDPISY (od {od_text})  —  celkem {len(predpisy)}", n_cols)
    row = zapis_hlavicku(ws, row, ["#", "Datum", "Vydaný lék", "ATC", "Návod", "Lékař", "Odbornost", "Pracoviště a adresa"])
    for i, r in enumerate(predpisy, 1):
        nevyzv = bool(r["nevyzvednuto"])
        adresa = (f"{r.get('pzs_nazev') or ''}, {r.get('ulice') or ''}, "
                  f"{r.get('psc') or ''} {r.get('mesto') or ''}").strip(", ")
        row = zapis_radek(ws, row, [
            i,
            r["datum_vystaveni"].strftime("%d.%m.%Y") if r["datum_vystaveni"] else "",
            r["vydany_lek"],
            r.get("atc") or "",
            r.get("navod") or "",
            f"{r['lek_prijmeni']} {r['lek_jmena']}",
            odbornost_z_icp(r.get("icp")),
            adresa,
        ], highlight=nevyzv)

    # ── Autofit sloupců a řádků ───────────────────────────────────────────────
    autofit(ws, min_width=5, max_width=60)

    # Zmraz záhlaví
    ws.freeze_panes = "A2"

    return wb


def main():
    datum_od = parse_datum(DATUM_OD, "DATUM_OD") if DATUM_OD else None

    fb_pac         = najdi_v_firebirdu(RODNE_CISLO)
    prijmeni       = fb_pac["prijmeni"]
    datum_narozeni = fb_pac["datnar"]

    print(f"Nacitam data: {prijmeni} {fb_pac['jmeno']}  nar. {datum_narozeni} ...")
    pac, lekari, predpisy = nacti_data(prijmeni, datum_narozeni, datum_od)
    print(f"  {len(lekari)} lekaru, {len(predpisy)} predpisu")

    wb = vytvor_excel(pac, lekari, predpisy, datum_od, fb_pac)

    vyst = Path(VYSTUP_DIR) if VYSTUP_DIR else Path(__file__).parent
    zaklad = vyst / f"LZ_{prijmeni}_{fb_pac['jmeno']}_{datum_narozeni}.xlsx"
    if not zaklad.exists():
        soubor = zaklad
    else:
        i = 2
        while True:
            soubor = vyst / f"LZ_{prijmeni}_{fb_pac['jmeno']}_{datum_narozeni}_v{i}.xlsx"
            if not soubor.exists():
                break
            i += 1
    wb.save(soubor)
    print(f"Ulozeno: {soubor}")


if __name__ == "__main__":
    main()
