"""
pn_report.py – Report aktivních pracovních neschopností
Generuje PDF a posílá na výchozí tiskárnu.

Spuštění:
    python pn_report.py           # vytvoří PDF a vytiskne
    python pn_report.py --no-print  # jen vytvoří PDF (pro testování)

Požadavky:
    pip install reportlab pywin32
"""

import fdb
import sys
import os
import tempfile
from datetime import date, datetime

from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import cm
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont

# ---------------------------------------------------------------------------
# Konfigurace
# ---------------------------------------------------------------------------

DB_DSN      = r'localhost:c:\medicus 3\data\medicus.fdb'
DB_USER     = 'SYSDBA'
DB_PASS     = 'masterkey'
DB_CHARSET  = 'win1250'

# Pokud chcete soubor uložit trvale, nastavte výstupní adresář:
OUTPUT_DIR  = None   # None = dočasný soubor, smaže se po tisku
#OUTPUT_DIR = r'u:\Dropbox\!!!Days\Downloads Z230'

# ---------------------------------------------------------------------------
# Dotaz – aktivní PN (konnes IS NULL nebo v budoucnosti, storno='F')
# ---------------------------------------------------------------------------

SQL = """
    SELECT
        nes.id                                          AS idnes,
        nes.idpac,
        TRIM(kar.prijmeni) || ', ' || TRIM(kar.jmeno)  AS jmeno,
        kar.rodcis,
        nes.zacnes,
        nes.konnes,
        nes.diagno,
        COALESCE(nes.ecn, nes.cisnes)                  AS cisnes,
        (SELECT MAX(h.datum) FROM hpn h
         WHERE h.idnes = nes.id AND h.typ = 'P' AND h.storno = 'F') AS posl_potvrzeni
    FROM nes, kar
    WHERE nes.zacnes <= current_date
      AND nes.konnes IS NULL
      AND nes.idpac = kar.idpac
      AND nes.pracne = 'A'
      AND nes.storno <> 'T'
      AND (
          NOT EXISTS (SELECT id FROM nesd WHERE nesd.idnes = nes.id)
          OR (SELECT FIRST 1 kam FROM nesd WHERE nesd.idnes = nes.id
              ORDER BY nesd.datum DESC, nesd.id DESC) = 'N'
      )
    ORDER BY kar.prijmeni ASC, kar.jmeno ASC
"""

# ---------------------------------------------------------------------------
# Pomocné funkce
# ---------------------------------------------------------------------------

def fmt_date(val):
    """Datum → DD.MM.YYYY nebo prázdný řetězec."""
    if val is None:
        return ''
    if isinstance(val, (date, datetime)):
        return val.strftime('%d.%m.%Y')
    return str(val)

def fmt_str(val):
    if val is None:
        return ''
    return str(val).strip()

def delka_pn(zacnes, konnes):
    """Počet dnů PN (od začátku do dnes / do konce)."""
    if zacnes is None:
        return ''
    end = konnes if konnes else date.today()
    if isinstance(zacnes, datetime):
        zacnes = zacnes.date()
    if isinstance(end, datetime):
        end = end.date()
    if isinstance(zacnes, date) and isinstance(end, date):
        days = (end - zacnes).days + 1
        return str(days)
    return ''

# ---------------------------------------------------------------------------
# Načtení fontu s českou diakritikou
# ---------------------------------------------------------------------------

def register_font():
    """
    Zkusí zaregistrovat DejaVuSans (umí win1250 znaky).
    Fallback: Helvetica (bez diakritiky – nouzové řešení).
    """
    font_paths = [
        r'C:\Windows\Fonts\DejaVuSans.ttf',
        r'C:\Windows\Fonts\arial.ttf',
        r'C:\Windows\Fonts\segoeui.ttf',
    ]
    for path in font_paths:
        if os.path.exists(path):
            name = os.path.splitext(os.path.basename(path))[0]
            try:
                pdfmetrics.registerFont(TTFont(name, path))
                pdfmetrics.registerFont(TTFont(name + '-Bold',
                    path.replace('.ttf', 'bd.ttf') if 'arial' in path.lower()
                    else path.replace('.ttf', '-Bold.ttf')
                    if os.path.exists(path.replace('.ttf', '-Bold.ttf'))
                    else path
                ))
                return name, name + '-Bold'
            except Exception:
                continue
    return 'Helvetica', 'Helvetica-Bold'

# ---------------------------------------------------------------------------
# Generování PDF
# ---------------------------------------------------------------------------

def build_pdf(rows, output_path, font_name, font_bold):
    today_str = date.today().strftime('%d.%m.%Y')
    weekday_cs = ['pondělí', 'úterý', 'středa', 'čtvrtek', 'pátek', 'sobota', 'neděle']
    weekday = weekday_cs[date.today().weekday()]

    doc = SimpleDocTemplate(
        output_path,
        pagesize=A4,
        topMargin=1.5*cm,
        bottomMargin=1.5*cm,
        leftMargin=1.5*cm,
        rightMargin=1.5*cm,
    )

    styles = getSampleStyleSheet()

    def para(text, size=10, bold=False, align='LEFT', color=colors.black):
        fn = font_bold if bold else font_name
        al = {'LEFT': 0, 'CENTER': 1, 'RIGHT': 2}.get(align, 0)
        from reportlab.platypus import Paragraph as P
        from reportlab.lib.styles import ParagraphStyle
        st = ParagraphStyle('x', fontName=fn, fontSize=size,
                            textColor=color, alignment=al, leading=size*1.3)
        return P(text, st)

    story = []

    # Záhlaví
    story.append(para('MUDr. Buzalková Michaela – ordinace praktického lékaře',
                       size=9, color=colors.grey))
    story.append(para(f'Aktivní pracovní neschopnosti',
                       size=16, bold=True))
    story.append(para(f'Vytištěno: {weekday} {today_str}   |   Počet záznamů: {len(rows)}',
                       size=9, color=colors.grey))
    story.append(Spacer(1, 0.4*cm))

    if not rows:
        story.append(para('Žádné aktivní pracovní neschopnosti.', size=12))
        doc.build(story)
        return

    # Záhlaví tabulky
    headers = ['#', 'Příjmení a jméno', 'Rod. číslo', 'Začátek PN',
               'Dnů', 'Diagnóza', 'Posl. potvrzení', 'Dní od potvr.']

    col_widths = [0.7*cm, 5.5*cm, 2.8*cm, 2.4*cm, 1.4*cm, 2.2*cm, 3.0*cm, 2.2*cm]

    table_data = [headers]
    overdue_rows = []  # indexy řádků kde je potvrzení po splatnosti

    for idx, row in enumerate(rows, start=1):
        idnes, idpac, jmeno, rodcis, zacnes, konnes, diagno, cisnes, posl_potvrzeni = row

        # Počet dní od posledního potvrzení
        if posl_potvrzeni is not None:
            pp = posl_potvrzeni.date() if isinstance(posl_potvrzeni, datetime) else posl_potvrzeni
            dni_od = (date.today() - pp).days
            dni_od_str = str(dni_od)
            if dni_od > 14:
                overdue_rows.append(idx + 1)  # +1 kvůli záhlaví
        else:
            # Žádné potvrzení – počítáme od začátku PN
            zac = zacnes.date() if isinstance(zacnes, datetime) else zacnes
            if zac:
                dni_od = (date.today() - zac).days
                dni_od_str = str(dni_od) + ' (!)'
                if dni_od > 14:
                    overdue_rows.append(idx + 1)
            else:
                dni_od_str = '—'

        table_data.append([
            str(idx),
            fmt_str(jmeno),
            fmt_str(rodcis),
            fmt_date(zacnes),
            delka_pn(zacnes, konnes),
            fmt_str(diagno),
            fmt_date(posl_potvrzeni) if posl_potvrzeni else '—',
            dni_od_str,
        ])

    tbl = Table(table_data, colWidths=col_widths, repeatRows=1)

    style = TableStyle([
        # Záhlaví
        ('BACKGROUND',   (0, 0), (-1, 0), colors.HexColor('#2F5496')),
        ('TEXTCOLOR',    (0, 0), (-1, 0), colors.white),
        ('FONTNAME',     (0, 0), (-1, 0), font_bold),
        ('FONTSIZE',     (0, 0), (-1, 0), 8),
        ('ALIGN',        (0, 0), (-1, 0), 'CENTER'),
        ('BOTTOMPADDING',(0, 0), (-1, 0), 5),
        ('TOPPADDING',   (0, 0), (-1, 0), 5),
        # Data
        ('FONTNAME',     (0, 1), (-1, -1), font_name),
        ('FONTSIZE',     (0, 1), (-1, -1), 8),
        ('ALIGN',        (0, 1), (0, -1), 'CENTER'),   # #
        ('ALIGN',        (5, 1), (5, -1), 'RIGHT'),    # Dnů
        ('VALIGN',       (0, 0), (-1, -1), 'MIDDLE'),
        ('TOPPADDING',   (0, 1), (-1, -1), 3),
        ('BOTTOMPADDING',(0, 1), (-1, -1), 3),
        # Mřížka
        ('GRID',         (0, 0), (-1, -1), 0.3, colors.HexColor('#AAAAAA')),
        ('LINEBELOW',    (0, 0), (-1, 0), 1, colors.HexColor('#2F5496')),
        # Zebra
        *[('BACKGROUND', (0, i), (-1, i), colors.HexColor('#DCE6F1'))
          for i in range(2, len(table_data), 2)],
        # Červené zvýraznění – potvrzení po splatnosti (> 14 dní)
        *[('BACKGROUND',  (6, i), (7, i), colors.HexColor('#F4CCCC'))
          for i in overdue_rows],
        *[('TEXTCOLOR',   (6, i), (7, i), colors.HexColor('#CC0000'))
          for i in overdue_rows],
        *[('FONTNAME',    (6, i), (7, i), font_bold)
          for i in overdue_rows],
    ])
    tbl.setStyle(style)
    story.append(tbl)

    # Patička
    story.append(Spacer(1, 0.5*cm))
    story.append(para(f'--- konec reportu ({len(rows)} záznamů) ---',
                       size=8, color=colors.grey, align='CENTER'))

    doc.build(story)

# ---------------------------------------------------------------------------
# Tisk
# ---------------------------------------------------------------------------

def print_pdf(path):
    """Pošle PDF na výchozí tiskárnu přes Windows ShellExecute."""
    try:
        import win32api
        win32api.ShellExecute(0, 'print', path, None, '.', 0)
        print(f'Odesláno na tiskárnu: {path}')
    except ImportError:
        # Fallback – otevře soubor v PDF prohlížeči (ruční tisk)
        print('pywin32 není nainstalován, otevírám PDF...')
        os.startfile(path)

# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------

def main():
    no_print = '--no-print' in sys.argv

    # Připojení k DB
    print('Připojuji se k DB...')
    conn = fdb.connect(dsn=DB_DSN, user=DB_USER, password=DB_PASS, charset=DB_CHARSET)
    cur = conn.cursor()

    print('Načítám aktivní PN...')
    cur.execute(SQL)
    rows = cur.fetchall()
    conn.close()
    print(f'Nalezeno {len(rows)} aktivních PN.')

    # Font
    font_name, font_bold = register_font()
    print(f'Font: {font_name}')

    # Výstupní soubor
    if OUTPUT_DIR:
        os.makedirs(OUTPUT_DIR, exist_ok=True)
        out_path = os.path.join(OUTPUT_DIR,
                                date.today().strftime('%Y-%m-%d') + '_pn_report.pdf')
    else:
        fd, out_path = tempfile.mkstemp(suffix='_pn_report.pdf')
        os.close(fd)

    print(f'Generuji PDF: {out_path}')
    build_pdf(rows, out_path, font_name, font_bold)
    print('PDF hotovo.')

    if no_print:
        print('(tisk přeskočen – --no-print)')
        # Otevřeme pro náhled
        os.startfile(out_path)
    else:
        print_pdf(out_path)
        # Dočasný soubor necháme – tiskárna ho potřebuje přečíst
        # Windows ho smaže sám po zpracování tisku (temp adresář)

if __name__ == '__main__':
    main()
