import sys, io, re, os, glob
from datetime import date, datetime
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
import fdb
import openpyxl
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side

VYSTUPNI_ADRESAR = r'z:\Dropbox\Ordinace\Reporty'
NAZEV_REPORTU    = 'Dekurzy'
DATUM_OD         = '2025-01-01'
DATUM_DO         = date.today().strftime('%Y-%m-%d')


conn = fdb.connect(
    host='192.168.1.10', database=r'm:\MEDICUS\data\medicus.FDB',
    user='sysdba', password='masterkey',charset='WIN1250')

cur = conn.cursor()

cur.execute(f"""
    SELECT d.DATUM, d.CAS, u.ZKRATKA, k.PRIJMENI, k.JMENO, k.RODCIS, k.POJ, d.DEKURS
    FROM DEKURS d
    JOIN KAR k ON k.IDPAC = d.IDPAC
    LEFT JOIN UZIVATEL u ON u.IDUZI = d.IDUZI
    WHERE d.DATUM >= '{DATUM_OD}' AND d.DATUM <= '{DATUM_DO}'
    ORDER BY d.DATUM DESC, d.CAS DESC, k.PRIJMENI, k.JMENO
""")
raw_rows = cur.fetchall()

TOP_TYPY = ['VykA', 'Rec', 'Files', 'MEDLAB', 'Lab', 'Ock', 'Nes', 'Lec', 'SpecVys', 'PlaPac']

def rtf_na_text(rtf):
    """Jednoduchý převod RTF na čistý text."""
    # Odstraň info blok (bookmarky apod.)
    text = re.sub(r'\{\\info.*?\}', '', rtf, flags=re.DOTALL)
    # Odstraň ostatní skupiny v {} rekurzivně (fonty, barvy apod.)
    for _ in range(6):
        text = re.sub(r'\{[^{}]*\}', '', text)
    # Nový řádek za \par \line
    text = re.sub(r'\\par\b\s*', '\n', text)
    text = re.sub(r'\\line\b\s*', '\n', text)
    # Dekóduj RTF hex escape sekvence (\'xx) jako cp1250 → správná čeština
    def decode_hex(m):
        try:
            return bytes.fromhex(m.group(1)).decode('cp1250')
        except Exception:
            return ''
    text = re.sub(r"\\'([0-9a-fA-F]{2})", decode_hex, text)
    # Odstraň ostatní RTF příkazy
    text = re.sub(r'\\[a-zA-Z]+\-?[0-9]*\s?', '', text)
    text = re.sub(r'[{}\\]', '', text)
    # Vyčisti prázdné řádky a whitespace
    lines = [l.strip() for l in text.splitlines()]
    lines = [l for l in lines if l]
    return '\n'.join(lines)

# Parse dekurzů
rows = []
for datum, cas, zkratka, prijmeni, jmeno, rodcis, poj, dekurs_blob in raw_rows:
    if hasattr(dekurs_blob, 'read'):
        rtf = dekurs_blob.read()
        dekurs_blob.close()
    else:
        rtf = dekurs_blob or ''
    pocty = {}
    ids_by_typ = {t: [] for t in TOP_TYPY}
    ids_ostatni = []
    for nazev, typ, rid in re.findall(r'"([^"]+)","([A-Za-z]+):(\d+)"', rtf):
        pocty[typ] = pocty.get(typ, 0) + 1
        if typ in ids_by_typ:
            ids_by_typ[typ].append(int(rid))
        else:
            ids_ostatni.append((typ, int(rid), nazev))
    top = [pocty.get(t, 0) for t in TOP_TYPY]
    ostatni = sum(v for k, v in pocty.items() if k not in TOP_TYPY)
    iniciala = jmeno[0] + '.' if jmeno and jmeno.strip() else ''
    jmeno_cel = f"{prijmeni.strip()}, {iniciala}" if prijmeni else iniciala
    text_dekurzu = rtf_na_text(rtf)
    rows.append((datum, cas, zkratka, jmeno_cel, rodcis, poj, top, ostatni, ids_by_typ, ids_ostatni, text_dekurzu))

# ── Načtení detailů z DB ────────────────────────────────────────────────────
def fetch_details(cur, table, pk, id_col, fields, ids):
    if not ids:
        return {}
    result = {}
    batch_size = 1000
    for i in range(0, len(ids), batch_size):
        batch = ids[i:i+batch_size]
        ph = ','.join('?' * len(batch))
        cur.execute(f"SELECT {pk}, {','.join(fields)} FROM {table} WHERE {id_col} IN ({ph})", batch)
        for row in cur.fetchall():
            result[row[0]] = row[1:]
    return result

def get_ids(rows, typ):
    return list({rid for *_, ids_by_typ, _, _text in rows for rid in ids_by_typ[typ]})

rec_det    = fetch_details(cur, 'RECEPT',  'ID',       'ID',       ['LEK','DSIG'], get_ids(rows,'Rec'))
vyka_det   = fetch_details(cur, 'DOKLADD', 'ID',       'ID',       ['KOD','DDGN','BODY'], get_ids(rows,'VykA'))
files_det  = fetch_details(cur, 'FILES',   'ID',       'ID',       ['FILENAME','DATUM'], get_ids(rows,'Files'))
medlab_det = fetch_details(cur, 'HISTDOC', 'ID',       'ID',       ['DATUM','TYP'], get_ids(rows,'MEDLAB'))
lab_det    = fetch_details(cur, 'LABVH',   'IDVH',     'IDVH',     ['DATUM','CISLO'], get_ids(rows,'Lab'))
ock_det    = fetch_details(cur, 'OCKZAZ',  'ID',       'ID',       ['DATUM','LATKA'], get_ids(rows,'Ock'))
nes_det    = fetch_details(cur, 'NES',     'ID',       'ID',       ['ZACNES','KONNES'], get_ids(rows,'Nes'))
lec_det    = fetch_details(cur, 'LECD',    'ID',       'ID',       ['KOD','DATOSE'], get_ids(rows,'Lec'))
spec_det   = fetch_details(cur, 'SPECVYS', 'IDSPECVYS','IDSPECVYS',['TYP','DATUM'], get_ids(rows,'SpecVys'))
pla_det    = fetch_details(cur, 'PLA',     'IDPLA',    'IDPLA',    ['DATUM','CENA','DOKLAD'], get_ids(rows,'PlaPac'))

conn.close()
print(f"Načteno {len(rows)} dekurzů")

# ── Styly ──────────────────────────────────────────────────────────────────
tenka_cara  = Side(style='thin', color='AAAAAA')
ohraniceni  = Border(left=tenka_cara, right=tenka_cara, top=tenka_cara, bottom=tenka_cara)
hl_font     = Font(bold=True, color="FFFFFF")
hl_fill     = PatternFill("solid", fgColor="2E75B6")
r_fill      = [PatternFill("solid", fgColor="FFFFFF"), PatternFill("solid", fgColor="DCE6F1")]

BARVY_LISTU = {
    'Recepty':    ('1F6B33', 'E2EFDA'),
    'Výkony':     ('2E4057', 'D6E4F0'),
    'Soubory':    ('7B3F00', 'FAE5D3'),
    'Žádanky':    ('4A235A', 'F5EEF8'),
    'Lab výsl.':  ('145A32', 'D5F5E3'),
    'Očkování':   ('7E5109', 'FDEBD0'),
    'Neschop.':   ('922B21', 'FADBD8'),
    'Léčiva':     ('1A5276', 'D6EAF8'),
    'SpecVys':    ('0B5345', 'D1F2EB'),
    'Platby':     ('4D5656', 'EAECEE'),
    'Ostatní':    ('2C3E50', 'EBF5FB'),
}

def zapis_hlavicku(ws, sloupce, sirky, barva_hex):
    hl_fill_l = PatternFill("solid", fgColor=barva_hex)
    for col, (nazev, sirka) in enumerate(zip(sloupce, sirky), start=1):
        cell = ws.cell(row=1, column=col, value=nazev)
        cell.font      = hl_font
        cell.fill      = hl_fill_l
        cell.alignment = Alignment(horizontal='center')
        cell.border    = ohraniceni
        ws.column_dimensions[cell.column_letter].width = sirka

def zapis_radek(ws, row_i, hodnoty, zarovnani, barva_hex):
    fill = PatternFill("solid", fgColor="FFFFFF") if row_i % 2 == 0 \
           else PatternFill("solid", fgColor=barva_hex)
    for col_i, (val, align) in enumerate(zip(hodnoty, zarovnani), start=1):
        cell = ws.cell(row=row_i, column=col_i, value=val)
        cell.fill      = fill
        cell.border    = ohraniceni
        cell.alignment = Alignment(horizontal=align)
        if col_i == 1 and isinstance(val, __import__('datetime').date):
            cell.number_format = 'DD.MM.YYYY'

def hyperlink_cell(ws, row_i, col_i, cil_list, cil_radek, text, barva_hex):
    fill = PatternFill("solid", fgColor="FFFFFF") if row_i % 2 == 0 \
           else PatternFill("solid", fgColor=barva_hex)
    cell = ws.cell(row=row_i, column=col_i)
    cell.value      = str(text)
    # Název listu s mezerou musí být v apostrofech
    sheet_ref = f"'{cil_list}'" if ' ' in cil_list else cil_list
    cell.hyperlink  = f'#{sheet_ref}!A{cil_radek}'
    cell.font       = Font(color="0000FF", underline='single')
    cell.fill       = fill
    cell.border     = ohraniceni
    cell.alignment  = Alignment(horizontal='center')

# ── Workbook ───────────────────────────────────────────────────────────────
wb = openpyxl.Workbook()

LISTY = [
    ('Recepty',   'Rec',     rec_det,    ['Datum','Jméno','Recept','Dávkování'],              [12,25,25,12],     None),
    ('Výkony',    'VykA',    vyka_det,   ['Datum','Jméno','Kód výkonu','Diagnóza','Body'],    [12,25,14,10,8],   None),
    ('Soubory',   'Files',   files_det,  ['Datum','Jméno','Soubor','Datum souboru'],          [12,25,35,14],     None),
    ('Žádanky',   'MEDLAB',  medlab_det, ['Datum','Jméno','Typ'],                             [12,25,15],        None),
    ('Lab výsl.', 'Lab',     lab_det,    ['Datum','Jméno','Číslo'],                           [12,25,20],        None),
    ('Očkování',  'Ock',     ock_det,    ['Datum','Jméno','Datum očkování','Vakcína'],         [12,25,14,30],     None),
    ('Neschop.',  'Nes',     nes_det,    ['Datum','Jméno','Od','Do'],                         [12,25,12,12],     None),
    ('Léčiva',    'Lec',     lec_det,    ['Datum','Jméno','Kód','Datum výkonu'],              [12,25,12,14],     None),
    ('SpecVys',   'SpecVys', spec_det,   ['Datum','Jméno','Typ vyšetření','Datum vyšetření'], [12,25,25,14],     None),
    ('Platby',    'PlaPac',  pla_det,    ['Datum','Jméno','Datum platby','Částka','Doklad'],  [12,25,14,12,15],  None),
    ('Ostatní',   None,      None,       ['Datum','Jméno','Typ','ID','Název'],                [12,25,12,10,30],  None),
]

ws_d = wb.active
ws_d.title = "Dekurz"

# List "Text dekurzu" hned za Dekurzem
ws_text = wb.create_sheet("Text dekurzu")

ws_listy = {}
for nazev, *_ in LISTY:
    ws_listy[nazev] = wb.create_sheet(nazev)

for nazev, typ, det, sloupce, sirky, _ in LISTY:
    barva_hl, _ = BARVY_LISTU[nazev]
    zapis_hlavicku(ws_listy[nazev], sloupce, sirky, barva_hl)
    ws_listy[nazev].freeze_panes = 'A2'

# Záhlaví listu "Text dekurzu"
zapis_hlavicku(ws_text,
               ['Datum', 'Čas', 'Lékař', 'Jméno', 'Rodné číslo', 'Text dekurzu'],
               [12,       8,     8,       25,       14,             100],
               '2E75B6')
ws_text.freeze_panes = 'A2'
row_ptr_text = 2

# Zobrazované názvy sloupců pro TOP_TYPY (stejné pořadí)
NAZVY_TYPY = ['VykA', 'Rec', 'Files', 'Žádanky', 'Lab výsl.', 'Ock', 'Nes', 'Lec', 'SpecVys', 'PlaPac']

# Záhlaví Dekurz – sloupce A–R
nazvy_d = ['Datum', 'Čas', 'Lékař', 'Jméno', 'Rodné číslo', 'Pojišťovna'] + ['HodVyk'] + NAZVY_TYPY + ['Ostatní']
sirky_d = [12,       8,     8,       25,       14,             12          ] + [10]        + [38, 8, 8, 8, 8, 8, 8, 8, 8, 8] + [8]
zapis_hlavicku(ws_d, nazvy_d, sirky_d, '2E75B6')
ws_d.freeze_panes = 'A2'
ws_d.auto_filter.ref = f"A1:R{len(rows)+1}"

row_ptr = {nazev: 2 for nazev, *_ in LISTY}

# ── Plnění dat ─────────────────────────────────────────────────────────────
def get_det_hodnoty(typ, rid, datum, jmeno_cel):
    if typ == 'Rec':
        d = rec_det.get(rid, ('', ''))
        return [datum, jmeno_cel, d[0] or '', d[1] or '']
    elif typ == 'VykA':
        d = vyka_det.get(rid, ('', '', 0))
        return [datum, jmeno_cel, d[0] or '', (d[1] or '').strip(), d[2] or 0]
    elif typ == 'Files':
        d = files_det.get(rid, ('', ''))
        return [datum, jmeno_cel, d[0] or '', d[1]]
    elif typ == 'MEDLAB':
        d = medlab_det.get(rid, ('', ''))
        return [datum, jmeno_cel, d[1] or '']
    elif typ == 'Lab':
        d = lab_det.get(rid, ('', ''))
        return [datum, jmeno_cel, d[1] or '']
    elif typ == 'Ock':
        d = ock_det.get(rid, ('', ''))
        return [datum, jmeno_cel, d[0], d[1] or '']
    elif typ == 'Nes':
        d = nes_det.get(rid, ('', ''))
        return [datum, jmeno_cel, d[0], d[1]]
    elif typ == 'Lec':
        d = lec_det.get(rid, ('', ''))
        return [datum, jmeno_cel, d[0] or '', d[1]]
    elif typ == 'SpecVys':
        d = spec_det.get(rid, ('', ''))
        return [datum, jmeno_cel, d[0] or '', d[1]]
    elif typ == 'PlaPac':
        d = pla_det.get(rid, ('', '', ''))
        return [datum, jmeno_cel, d[0], d[1], d[2] or '']
    return []

ZAROVNANI = {
    'Recepty':    ['left','left','left','center'],
    'Výkony':     ['left','left','center','center','right'],
    'Soubory':    ['left','left','left','left'],
    'Žádanky':    ['left','left','center'],
    'Lab výsl.':  ['left','left','center'],
    'Očkování':   ['left','left','left','left'],
    'Neschop.':   ['left','left','left','left'],
    'Léčiva':     ['left','left','center','left'],
    'SpecVys':    ['left','left','left','left'],
    'Platby':     ['left','left','left','right','center'],
    'Ostatní':    ['left','left','center','center','left'],
}

for row_i, (datum, cas, zkratka, jmeno_cel, rodcis, poj, top, ostatni, ids_by_typ, ids_ostatni, text_dekurzu) in enumerate(rows, start=2):
    fill_d = r_fill[row_i % 2]
    for col_i in range(1, len(nazvy_d) + 1):
        ws_d.cell(row=row_i, column=col_i).fill   = fill_d
        ws_d.cell(row=row_i, column=col_i).border = ohraniceni

    ws_d.cell(row=row_i, column=1, value=datum).number_format = 'DD.MM.YYYY'
    ws_d.cell(row=row_i, column=2, value=str(cas)[:5] if cas else '').alignment = Alignment(horizontal='center')
    ws_d.cell(row=row_i, column=3, value=zkratka or '').alignment = Alignment(horizontal='center')
    ws_d.cell(row=row_i, column=4, value=jmeno_cel)
    # Sloupec 5 – Rodné číslo jako hyperlink na list "Text dekurzu"
    hyperlink_cell(ws_d, row_i, 5, 'Text dekurzu', row_ptr_text, rodcis or '', 'DCE6F1')
    ws_d.cell(row=row_i, column=6, value=poj or '').alignment = Alignment(horizontal='center')

    # Sloupec G – HodVyk (součet bodů všech výkonů dekurzu)
    hodvyk = sum((vyka_det.get(rid, ('', '', 0))[2] or 0) for rid in ids_by_typ['VykA'])
    cell_hv = ws_d.cell(row=row_i, column=7, value=hodvyk if hodvyk else '')
    cell_hv.alignment = Alignment(horizontal='center')

    for col_off, (typ, pocet) in enumerate(zip(TOP_TYPY, top)):
        col_i = 8 + col_off
        if pocet == 0:
            continue
        nazev_listu = next((n for n, t, *_ in LISTY if t == typ), None)
        if nazev_listu and ids_by_typ[typ]:
            _, barva_ll = BARVY_LISTU[nazev_listu]
            # Pro výkony (VykA) přidej kódy do závorky
            if typ == 'VykA':
                kody = [str(vyka_det.get(rid, ('',))[0] or '').strip() for rid in ids_by_typ[typ]]
                kody_str = ', '.join(k for k in kody if k)
                display_text = f"{pocet} ({kody_str})" if kody_str else pocet
            else:
                display_text = pocet
            hyperlink_cell(ws_d, row_i, col_i, nazev_listu, row_ptr[nazev_listu], display_text, barva_ll[1:] if len(barva_ll) > 6 else 'DCE6F1')
            ws_det = ws_listy[nazev_listu]
            barva_hl, barva_r = BARVY_LISTU[nazev_listu]
            for rid in ids_by_typ[typ]:
                hodnoty = get_det_hodnoty(typ, rid, datum, jmeno_cel)
                zarovnani_l = ZAROVNANI.get(nazev_listu, ['left']*10)
                zapis_radek(ws_det, row_ptr[nazev_listu], hodnoty, zarovnani_l, barva_r)
                row_ptr[nazev_listu] += 1
        else:
            ws_d.cell(row=row_i, column=col_i, value=pocet).alignment = Alignment(horizontal='center')

    if ostatni:
        ws_det = ws_listy['Ostatní']
        barva_hl, barva_r = BARVY_LISTU['Ostatní']
        hyperlink_cell(ws_d, row_i, 18, 'Ostatní', row_ptr['Ostatní'], ostatni, barva_r)
        for typ, rid, nazev in ids_ostatni:
            zapis_radek(ws_det, row_ptr['Ostatní'],
                        [datum, jmeno_cel, typ, rid, nazev],
                        ZAROVNANI['Ostatní'], barva_r)
            row_ptr['Ostatní'] += 1

    # Zápis do listu "Text dekurzu"
    fill_t = r_fill[row_ptr_text % 2]
    for col_i in range(1, 7):
        ws_text.cell(row=row_ptr_text, column=col_i).fill   = fill_t
        ws_text.cell(row=row_ptr_text, column=col_i).border = ohraniceni
    c1 = ws_text.cell(row=row_ptr_text, column=1, value=datum)
    c1.number_format = 'DD.MM.YYYY'
    c1.alignment = Alignment(horizontal='left', vertical='center')
    ws_text.cell(row=row_ptr_text, column=2, value=str(cas)[:5] if cas else '').alignment = Alignment(horizontal='center', vertical='center')
    ws_text.cell(row=row_ptr_text, column=3, value=zkratka or '').alignment = Alignment(horizontal='center', vertical='center')
    ws_text.cell(row=row_ptr_text, column=4, value=jmeno_cel).alignment = Alignment(horizontal='left', vertical='center')
    ws_text.cell(row=row_ptr_text, column=5, value=rodcis or '').alignment = Alignment(horizontal='left', vertical='center')
    cell_txt = ws_text.cell(row=row_ptr_text, column=6, value=text_dekurzu)
    cell_txt.alignment = Alignment(horizontal='left', vertical='top', wrap_text=True)
    row_ptr_text += 1

# Autofiltr na detailních listech
for nazev, *_ in LISTY:
    ws = ws_listy[nazev]
    max_col = ws.max_column
    max_row = ws.max_row
    if max_row > 1:
        ws.auto_filter.ref = f"A1:{ws.cell(row=1, column=max_col).column_letter}{max_row}"

# Smazat starý report
for stary in glob.glob(os.path.join(VYSTUPNI_ADRESAR, f'* {NAZEV_REPORTU}.xlsx')):
    os.remove(stary)
    print(f"Smazán: {stary}")

# Uložit nový
os.makedirs(VYSTUPNI_ADRESAR, exist_ok=True)
casova_znacka = datetime.now().strftime('%Y-%m-%d %H-%M-%S')
vystup = os.path.join(VYSTUPNI_ADRESAR, f'{casova_znacka} {NAZEV_REPORTU}.xlsx')
wb.save(vystup)
print(f"Uloženo: {vystup}")
for nazev, *_ in LISTY:
    print(f"  {nazev}: {row_ptr[nazev]-2} řádků")
