#!/usr/bin/env python3
"""NEMO web generator — lives NEXT TO the web it builds.

Location: ~/public_html/gen_web.py  (served at /pub/rhias/nemo/gen_web.py)
Reads:    ~/nemo/db.md  (property database — source of truth)
Writes:   ~/public_html/index.html  (public overview page)
Run:      python3 ~/public_html/gen_web.py [YYYY-MM-DD]
When:     end of EVERY /nemo scan (mandatory) and after any db.md edit.

index.html is GENERATED — never edit by hand. To change layout, edit THIS file.
Sections: ★ Prioritní (FAV ids) / 🆕 Nové / Aktivní / Archiv reportů.
Každá položka ukazuje datum PRVNÍHO SPATŘENÍ (sloupec "První výskyt" v db.md)
a v každé sekci se řadí podle něj — NEJNOVĚJŠÍ NAHOŘE (Kron 17.7.2026).
Active row = stav NEobsahuje staženo/prodáno/neaktivní/vyřazeno.
"""
import sys, re, glob, os, datetime

HERE = os.path.dirname(os.path.abspath(__file__))
DB = os.path.expanduser("~/nemo/db.md")
OUT = os.path.join(HERE, "index.html")
REPORTS = os.path.join(HERE, "reports")
FAV = {"9", "42", "99", "143"}  # Senešnice, Vinařice, Týnec-Krusičany (Kron 24.7.), Medonosy (Kron 14.8.) — Mlýn/Oleško (ID2) vyřazen z priorit 17.7.
VAL = {"9": "oceneni/senesnice.html", "2": "valuations/ID-02.html", "99": "oceneni/tynec-krusicany.html", "119": "oceneni/nova-ves-zajecov.html", "117": "oceneni/neveklov.html", "122": "oceneni/zloncice-dolanky.html", "121": "oceneni/rpety.html", "146": "oceneni/pysely-zajecice-tvrz.html"}  # published ocenění pages by ID

date = sys.argv[1] if len(sys.argv) > 1 else datetime.date.today().isoformat()

def parse():
    rows = []
    for ln in open(DB):
        if not ln.strip().startswith("|"):
            continue
        c = [x.strip() for x in ln.split("|")]
        if len(c) < 11 or c[1] in ("ID", "----", ":----"):
            continue
        if not re.match(r"^\d+$", c[1]):
            continue
        idn, lok, url, cena, poz, mn, first, over, stav = c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9]
        low = stav.lower()
        # active = not explicitly removed. Don't require literal "aktivní" (priority rows say "prioritní").
        active = not any(k in low for k in ("staženo", "prodáno", "prodano", "neaktivní", "neaktivni", "vyřazeno", "vyrazeno"))
        rows.append(dict(id=idn, lok=lok, url=url, cena=cena, poz=poz, mn=mn, first=first, stav=stav, active=active, novy="nové" in low))
    return rows

def dist_rank(mn):
    m = re.search(r"\d+", mn or "")
    if not m: return 3
    v = int(m.group())
    return 0 if v < 40 else (1 if v <= 50 else 2)

def size_rank(poz):
    digits = re.sub(r"\D", "", poz or "")
    if not digits: return 3
    v = int(digits)
    # Kron 25.7.: chtěj 10k m², 13k na zelenou, jinak rovnou červené
    return 0 if v >= 13000 else (1 if v >= 10000 else 2)

def price_rank(cena):
    digits = re.sub(r"\D", "", cena or "")
    if not digits: return 3          # "na dotaz" → neznámá, ignoruj
    # Kron 25.7.: cena > 35M → rovnou červená; jinak cenu barevně neřeš
    return 2 if int(digits) > 35_000_000 else 0

def crank(r):
    # barva = HORŠÍ (červenější) z dojezdu, velikosti a ceny; neznámé ignoruj
    known = [x for x in (dist_rank(r["mn"]), size_rank(r["poz"]), price_rank(r["cena"])) if x < 3]
    return max(known) if known else 3

def zone(r):
    return {0: ("zel", "🟢"), 1: ("zlu", "🟡"), 2: ("cer", "🔴")}.get(crank(r), ("", ""))

def fmt_poz(p):
    return (p + " m²") if re.search(r"\d", p) else p

def item(r):
    cls, emo = zone(r)
    mtxt = fmt_poz(r["poz"])
    if r["mn"] and re.search(r"\d", r["mn"]):
        mtxt += f" · {emo} {r['mn']} min"
    elif r["mn"]:
        mtxt += f" · {r['mn']}"
    mtxt += f" · ID {r['id']}"
    if r.get("first") and re.search(r"\d", r["first"]):
        mtxt += f' · <span class="seen">spatřeno {r["first"]}</span>'
    extra = f' · <a class="ocen" href="{VAL[r["id"]]}">→ ocenění</a>' if r["id"] in VAL else ""
    badge = '<span class="badge top">★</span>' if r["id"] in FAV else ""
    # NOTE: card is a <div>, not a wrapping <a> — nested <a> (listing + ocenění) is invalid
    # HTML and browsers flatten it so every click hit the listing (Kron 25.7. "oceneni nejsou ocenene").
    return (f'<div class="item">\n'
            f'  <a class="name" href="{r["url"]}" target="_blank" rel="noopener">{r["lok"]}</a>{badge}\n'
            f'  <span class="price">{r["cena"]}</span>\n'
            f'  <div class="meta {cls}">{mtxt}{extra}</div>\n</div>')

def minutes(r):
    m = re.search(r"\d+", r["mn"] or "")
    return int(m.group()) if m else 999

def seen(r):
    # sort key: first-seen date (ISO YYYY-MM-DD sorts lexically); newest first via reverse
    m = re.search(r"\d{4}-\d{2}-\d{2}", r.get("first") or "")
    return m.group() if m else "0000-00-00"

def zone_rank(r):
    # grupuje sekci po barvách; barva = kombinace dojezdu + velikosti (crank)
    return crank(r)

def order(lst):
    # dvoufázově (stabilní): uvnitř barvy nejnovější spatření nahoře, pak grupuj po barvách
    lst.sort(key=seen, reverse=True)
    lst.sort(key=zone_rank)
    return lst

rows = parse()
active = [r for r in rows if r["active"]]
fav = [r for r in active if r["id"] in FAV]
nove = [r for r in active if r["novy"] and r["id"] not in FAV]
rest = [r for r in active if not r["novy"] and r["id"] not in FAV]
# Řazení v každé sekci: grupuj po barvách 🟢→🟡→🔴, uvnitř barvy nejnovější spatření nahoře (Kron 17.7.)
order(nove); order(rest)

reps = sorted(glob.glob(os.path.join(REPORTS, "2026*.md")), reverse=True)
rep_links = "\n".join(
    f'<a class="item" href="reports/{os.path.basename(p)}"><span class="name">Report {os.path.basename(p)[:8]} →</span></a>'
    for p in reps[:8])

CSS = """* { margin:0; padding:0; box-sizing:border-box; }
body { font:15px/1.6 -apple-system, sans-serif; color:#222; background:#fff; padding:1.5rem 1rem; max-width:720px; margin:0 auto; }
h1 { font-size:1.8rem; font-weight:600; margin-bottom:0.3rem; }
.sub { color:#666; font-size:0.9rem; margin-bottom:1.5rem; }
h2 { font-size:1.1rem; font-weight:600; margin:2rem 0 0.8rem; border-bottom:1px solid #e0e0e0; padding-bottom:0.5rem; }
@media (min-width:600px){ body{padding:3rem 1.5rem;} .sub{margin-bottom:2rem;} }
a { color:#0066cc; text-decoration:none; } a:hover { text-decoration:underline; }
.item { display:block; margin-bottom:0.8rem; padding:1rem; border:1px solid #e0e0e0; }
.item:hover { border-color:#0066cc; background:#fafafa; }
.name { font-weight:500; font-size:1.05rem; display:inline-block; margin-bottom:0.3rem; color:#222; }
.name:hover { color:#0066cc; text-decoration:underline; }
.ocen { color:#0066cc; font-weight:600; }
.price { color:#0066cc; font-weight:500; }
.meta { color:#666; font-size:0.9rem; margin-top:0.4rem; }
@media (min-width:600px){ .item{padding:0.8rem;} .name{font-size:1rem;} .price{font-size:1rem;} .meta{font-size:0.85rem; margin-top:0.3rem;} }
.badge { display:inline-block; font-size:0.7rem; font-weight:600; text-transform:uppercase; padding:0.2rem 0.4rem; margin-left:0.5rem; border:1px solid #ccc; }
.top { border-color:#2e7d32; color:#2e7d32; }
.nav { margin-bottom:1.5rem; color:#999; font-size:0.9rem; padding-bottom:0.5rem; }
.zel{color:#2e7d32;} .zlu{color:#b58900;} .cer{color:#c62828;}
.seen{color:#999;}
.foot{color:#999;font-size:0.8rem;margin-top:2rem;border-top:1px solid #e0e0e0;padding-top:0.8rem;}
code{font-size:0.85em;background:#f4f4f4;padding:0.1rem 0.3rem;}"""

html = [f'<!doctype html><html lang="cs"><head><meta charset="utf-8">',
        '<meta name="viewport" content="width=device-width, initial-scale=1.0">',
        f'<title>NEMO — nemovitosti</title><style>\n{CSS}\n</style></head><body>',
        f'<div class="nav">aktualizováno {date} · {len(active)} aktivních</div>',
        '<h1>NEMO — nemovitosti</h1>',
        '<p class="sub">Zemědělské usedlosti a pozemky do 60 min od Prahy. Cíl pozemku 10 000 m². Barva = horší z dojezdu, velikosti a ceny: 🟢 ≥13 k m² &amp; &lt;40 min · 🟡 ≥10 k &amp; ≤50 min · 🔴 pod tím nebo cena &gt;35 M.</p>',
        '<div class="nav" style="margin-bottom:1.5rem">📌 <a href="vyjednavani/">Jak vyjednávat o ceně</a> — tahák před jednáním s prodávajícím</div>']
if fav:
    html.append("<h2>★ Prioritní</h2>")
    html += [item(r) for r in order(fav)]
if nove:
    html.append(f"<h2>🆕 Nové ({len(nove)})</h2>")
    html += [item(r) for r in nove]
html.append(f"<h2>Aktivní nemovitosti ({len(rest)})</h2>")
html += [item(r) for r in rest]
html.append("<h2>Další</h2>")
html.append('<a class="item" href="mapa.html"><span class="name">Mapa nemovitostí →</span><div class="meta">interaktivní mapa s dojezdy</div></a>')
if rep_links:
    html.append("<h2>Archiv reportů</h2>")
    html.append(rep_links)
html.append(f'<p class="foot">Auto-generováno z <code>db.md</code> skriptem '
            f'<a href="gen_web.py">gen_web.py</a> · {date} · {len(active)} aktivních</p>')
html.append("</body></html>")

open(OUT, "w").write("\n".join(html))
print(f"wrote {OUT}: {len(active)} active ({len(fav)} fav, {len(nove)} nové, {len(rest)} rest), {len(reps)} reports")
