"""
Stahování NOVÝCH protokolů ze schránek ČPZP — zastaví se při první již stažené zprávě.

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

Co dělá:
  - Prochází Schránku klienta a Schránku PZS od nejnovějších zpráv
  - Jakmile narazí na zprávu, která už je v Staženo/, okamžitě se zastaví
  - Vhodné pro pravidelné spouštění — stáhne jen to nové

POUŽITÍ:
  python 03_stahuj_nove.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("."))

    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 uz_stazeno(ref: str, nazev_base: str) -> str | None:
    """Vrátí název existujícího souboru, nebo None."""
    if ref:
        existing = glob.glob(os.path.join(STAZENO_DIR, f"*(Ref. {ref}).*"))
        if existing:
            return os.path.basename(existing[0])
    else:
        for ext in (".html", ".pdf", ".xml", ".zip"):
            if os.path.exists(os.path.join(STAZENO_DIR, nazev_base + ext)):
                return nazev_base + ext
    return None


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

    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

    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)

    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 stahuj_schranku(session: requests.Session, mailbox_url: str, seen_ids: set) -> tuple[int, bool]:
    """
    Prochází schránku od nejnovějších zpráv a stahuje, dokud nenarazí na již staženou.
    Vrátí (počet stažených, zda bylo dosaženo konce = nalezena stará zpráva).
    """
    stazeno = 0
    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:
            print("  Žádné další zprávy.")
            return stazeno, True

        for row in rows:
            msg_id = row["id"].replace("message-", "")
            if msg_id in seen_ids:
                continue
            seen_ids.add(msg_id)

            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_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 ""

            msg = {
                "id":    msg_id,
                "datum": parse_datum(datum_raw),
                "druh":  druh,
                "ref":   ref_c,
            }

            nazev_base = safe_name(f"{msg['datum']} {msg['druh']} (Ref. {msg['ref']})")
            existing = uz_stazeno(ref_c, nazev_base)
            if existing:
                print(f"  [stop] Nalezena již stažená zpráva: {existing}")
                return stazeno, True

            if stahni_zpravu(session, msg):
                stazeno += 1
            time.sleep(1.0)

        offset += PAGE_SIZE
        time.sleep(1.0)


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

    seen_ids: set = set()
    celkem = 0

    for url, name in SCHRANKY:
        print(f"\n=== {name} ({url}) ===")
        stazeno, _ = stahuj_schranku(session, url, seen_ids)
        celkem += stazeno

    print(f"\nHotovo: {celkem} nových zpráv staženo.")


if __name__ == "__main__":
    main()
