"""
Stahování protokolů ze schránek ČPZP.

Použij po 01_prihlaseni.py (ten uloží cpzp_cookies.json).

Co dělá:
  - Prochází Schránku klienta (/app/schranka/) a Schránku PZS (/app/schranka-pzs/)
  - Pro každou zprávu stáhne protokol (HTML soubor)
  - Ukládá do Staženo/ pod jménem: YYYY-MM-DD Druh zprávy (Ref. XXXXXXXX).html
  - Přeskočí soubory které už existují

POUŽITÍ:
  python 02_stahuj_vse.py
"""

import glob
import os
import re
import json
import sys
import time

import requests
from bs4 import BeautifulSoup

sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", ".."))
from Knihovny.najdi_dropbox import get_dropbox_root

BASE_URL     = "https://portal.cpzp.cz"
COOKIES_FILE = os.path.join(os.path.dirname(__file__), "cpzp_cookies.json")
STAZENO_DIR  = os.path.join(get_dropbox_root(), "Ordinace", "Dokumentace_ke_zpracování", "Zúčtovací zprávy", "205 ČPZP")

SCHRANKY = [
    ("/app/schranka/",     "Schránka klienta"),
    ("/app/schranka-pzs/", "Schránka PZS"),
]
PAGE_SIZE = 20


def make_session() -> requests.Session:
    with open(COOKIES_FILE, encoding="utf-8") as f:
        cookies = json.load(f)
    s = requests.Session()
    s.headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
    for c in cookies:
        s.cookies.set(c["name"], c["value"], domain=c["domain"].lstrip("."))

    # Ověř přihlášení
    r = s.get(f"{BASE_URL}/app/", timeout=15)
    if "frmPrihlasCert" in r.text:
        raise SystemExit("Cookies expirovala — nejdřív spusť 01_prihlaseni.py")
    return s


def parse_datum(datum_str: str) -> str:
    """'01.04.2026 22:05:42' → '2026-04-01'"""
    m = re.match(r"(\d{2})\.(\d{2})\.(\d{4})", datum_str.strip())
    if m:
        return f"{m.group(3)}-{m.group(2)}-{m.group(1)}"
    return "0000-00-00"


def safe_name(text: str) -> str:
    return re.sub(r'[\\/:*?"<>|]', "_", text).strip()


def get_message_rows(session: requests.Session, mailbox_url: str):
    """Vrátí všechny zprávy ze schránky (s paginací). Každá zpráva je dict."""
    messages = {}  # id -> dict, deduplication
    offset = 0
    while True:
        r = session.get(f"{BASE_URL}{mailbox_url}?offset={offset}", timeout=15)
        r.raise_for_status()
        soup = BeautifulSoup(r.content, "html.parser", from_encoding="utf-8")
        rows = soup.select("tr[id^='message-']")
        if not rows:
            break

        new_count = 0
        for row in rows:
            msg_id = row["id"].replace("message-", "")
            if msg_id in messages:
                continue
            cells = row.find_all("td")
            datum_raw  = cells[5].get_text(strip=True) if len(cells) > 5 else ""
            druh_ref   = cells[4].get_text(separator=" ", strip=True) if len(cells) > 4 else ""
            # druh_ref: "VYÚČTOVÁNÍ ZDRAVOTNÍ PÉČE Ref. č. 26274350"
            druh_match = re.match(r"^(.+?)\s+Ref\.\s*č\.\s*(\d+)", druh_ref)
            druh  = druh_match.group(1).strip() if druh_match else druh_ref
            ref_c = druh_match.group(2).strip() if druh_match else ""
            messages[msg_id] = {
                "id":    msg_id,
                "datum": parse_datum(datum_raw),
                "druh":  druh,
                "ref":   ref_c,
            }
            new_count += 1

        if new_count == 0:
            break
        offset += PAGE_SIZE
        time.sleep(1.0)

    return list(messages.values())


def stahni_zpravu(session: requests.Session, msg: dict) -> bool:
    """Stáhne protokol/přílohu zprávy. Vrátí True pokud staženo, False pokud přeskočeno."""
    nazev_base = safe_name(f"{msg['datum']} {msg['druh']} (Ref. {msg['ref']})")

    # Přeskoč pokud existuje soubor se stejným Ref. číslem (imunní vůči Unicode/mezera variantám)
    if msg["ref"]:
        existing = glob.glob(os.path.join(STAZENO_DIR, f"*(Ref. {msg['ref']}).*"))
        if existing:
            print(f"  [přeskočeno] {os.path.basename(existing[0])}")
            return False
    else:
        for ext in (".html", ".pdf", ".xml", ".zip"):
            if os.path.exists(os.path.join(STAZENO_DIR, nazev_base + ext)):
                print(f"  [přeskočeno] {nazev_base}{ext}")
                return False

    # Detail zprávy → najdi download link
    r = session.get(f"{BASE_URL}/app/schranka/detail/{msg['id']}/", timeout=15)
    r.raise_for_status()
    soup = BeautifulSoup(r.content, "html.parser", from_encoding="utf-8")
    dl_link = soup.find("a", href=re.compile(r"/app/schranka/protokol/"))
    if not dl_link:
        print(f"  [bez přílohy] {msg['id']} — {msg['druh']}")
        return False

    # Stáhni soubor (retry při timeoutu)
    for pokus in range(3):
        try:
            r2 = session.get(BASE_URL + dl_link["href"], timeout=60)
            r2.raise_for_status()
            break
        except requests.exceptions.Timeout:
            if pokus == 2:
                print(f"  [chyba] timeout po 3 pokusech — {msg['druh']} Ref. {msg['ref']}")
                return False
            time.sleep(3)

    # Urči příponu podle Content-Type nebo názvu souboru v linku
    ct = r2.headers.get("Content-Type", "")
    link_text = dl_link.get_text(strip=True)
    if link_text.lower().endswith(".pdf") or "pdf" in ct:
        ext = ".pdf"
    elif link_text.lower().endswith(".xml") or "xml" in ct:
        ext = ".xml"
    elif link_text.lower().endswith(".zip") or "zip" in ct:
        ext = ".zip"
    else:
        ext = ".html"

    cil = os.path.join(STAZENO_DIR, nazev_base + ext)
    with open(cil, "wb") as f:
        f.write(r2.content)
    print(f"  [OK] {os.path.basename(cil)}")
    return True


def main():
    os.makedirs(STAZENO_DIR, exist_ok=True)
    session = make_session()

    seen_ids: set = set()
    all_messages = []

    for url, name in SCHRANKY:
        print(f"\n=== {name} ({url}) ===")
        msgs = get_message_rows(session, url)
        new = [m for m in msgs if m["id"] not in seen_ids]
        seen_ids.update(m["id"] for m in msgs)
        all_messages.extend(new)
        print(f"  Nalezeno {len(msgs)} zpráv, z toho {len(new)} nových")

    print(f"\nCelkem ke stažení: {len(all_messages)} zpráv")
    stazeno = 0
    for msg in all_messages:
        if stahni_zpravu(session, msg):
            stazeno += 1
        time.sleep(1.0)

    print(f"\nHotovo: {stazeno} staženo, {len(all_messages) - stazeno} přeskočeno.")


if __name__ == "__main__":
    main()
