#!/usr/bin/env python3
"""
Собирает preview.html = header.html + вывод fancyindex + footer.html.

Середина повторяет шаблоны модуля буквально (template.h + make_content_buf
в ngx_http_fancyindex_module.c), поэтому превью можно верить: если тема
разъедется здесь, она разъедется и на боевом nginx.

Запуск:  python3 dev/make_preview.py  ->  preview.html в корне проекта
"""

import datetime
import html
import os
import sys
from urllib.parse import quote

URI = "/media/night-city/street-2077/"

# (имя, каталог?, размер в байтах, "дата")
ENTRIES = [
    ("archive",                      True,  0,          "2077-Jan-02 11:04"),
    ("raw-scans",                    True,  0,          "2077-Jan-14 22:51"),
    ("Уличные снимки",               True,  0,          "2077-Jan-15 02:32"),
    ("_neon_backup",                 True,  0,          "2076-Dec-30 08:12"),
    ("afterlife-bar-01.jpg",         False, 4_812_233,  "2077-Jan-15 02:31"),
    ("afterlife-bar-02.jpg",         False, 5_120_998,  "2077-Jan-15 02:31"),
    ("kabuki-market.png",            False, 12_884_901, "2077-Jan-14 23:47"),
    ("вид с Уотсона.webp",           False, 2_201_120,  "2077-Jan-13 19:02"),
    ("jig-jig-street.gif",           False, 18_446_744, "2077-Jan-12 03:15"),
    ("braindance-take-07.mp4",       False, 1_073_741_824, "2077-Jan-11 21:40"),
    ("samurai-never-fade-away.flac", False, 41_943_040, "2077-Jan-10 12:00"),
    ("ncpd-scanner-dump.zip",        False, 268_435_456, "2077-Jan-09 05:33"),
    ("relic-firmware.iso",           False, 4_294_967_296, "2076-Nov-02 00:01"),
    ("index-crawler.py",             False, 8_412,      "2077-Jan-08 14:22"),
    ("street-notes.md",              False, 3_209,      "2077-Jan-07 09:10"),
    ("cyberdeck-manual.pdf",         False, 7_340_032,  "2076-Aug-19 16:45"),
    ("kiroshi-optics.glb",           False, 22_020_096, "2077-Jan-06 18:30"),
    ("netrunner.exe",                False, 1_048_576,  "2077-Jan-05 04:04"),
    ("Rajdhani-Bold.ttf",            False, 148_620,    "2076-Jul-01 10:00"),
    ("scan.log",                     False, 512,        "2077-Jan-15 02:32"),
    ("no-extension-file",            False, 91_233,     "2077-Jan-04 07:07"),
]


def _fresh(**delta) -> str:
    """Дата в формате fancyindex_time_format по умолчанию: %Y-%b-%d %H:%M."""
    d = datetime.datetime.now() - datetime.timedelta(**delta)
    return f"{d.year}-{d.strftime('%b')}-{d.strftime('%d %H:%M')}"


# свежие записи — чтобы проверить относительное время («12 мин назад»)
ENTRIES += [
    ("just-uploaded.jpg",  False, 3_145_728, _fresh(minutes=12)),
    ("yesterday-dump.zip", False, 88_080_384, _fresh(hours=30)),
    ("last-month.mp4",     False, 734_003_200, _fresh(days=41)),
]

SIZES = ["EiB", "PiB", "TiB", "GiB", "MiB", "KiB", "B"]


def human(n: int) -> str:
    """Ровно как модуль: делит от эксбибайта вниз, байты — без десятичной части."""
    mult = 1024 ** 6
    j = 0
    while j < len(SIZES) - 1 and n < mult:
        mult //= 1024
        j += 1
    if j == len(SIZES) - 1:
        return f"{n} {SIZES[j]}"
    return f"{n / mult:.1f} {SIZES[j]}"


def build_listing(sort_args: str = "") -> str:
    esc = html.escape
    out = []
    # t05_body2: модуль дописывает экранированный URI и закрывает <h1> из header.html
    out.append(esc(URI) + "</h1>\n")
    # t06_list1
    out.append(
        '<table id="list"><thead><tr>'
        '<th colspan="2"><a href="?C=N&amp;O=A">File Name</a>&nbsp;'
        '<a href="?C=N&amp;O=D">&nbsp;&darr;&nbsp;</a></th>'
        '<th><a href="?C=S&amp;O=A">File Size</a>&nbsp;'
        '<a href="?C=S&amp;O=D">&nbsp;&darr;&nbsp;</a></th>'
        '<th><a href="?C=M&amp;O=A">Date</a>&nbsp;'
        '<a href="?C=M&amp;O=D">&nbsp;&darr;&nbsp;</a></th>'
        "</tr></thead>\n<tbody>"
    )
    # parent dir
    out.append(
        '<tr><td colspan="2" class="link"><a href="../%s">Parent directory/</a></td>'
        '<td class="size">-</td><td class="date">-</td></tr>\r\n' % sort_args
    )
    for name, is_dir, size, date in ENTRIES:
        href = quote(name) + ("/" + sort_args if is_dir else "")
        label = esc(name) + ("/" if is_dir else "")
        size_txt = "-" if is_dir else human(size)
        out.append(
            '<tr><td colspan="2" class="link">'
            f'<a href="{href}" title="{esc(name)}">{label}</a></td>'
            f'<td class="size">{size_txt}</td>'
            f'<td class="date">{date}</td></tr>\r\n'
        )
    # t07_list2
    out.append("</tbody></table>")
    return "".join(out)


def main() -> int:
    root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    try:
        header = open(os.path.join(root, "header.html"), encoding="utf-8").read()
        footer = open(os.path.join(root, "footer.html"), encoding="utf-8").read()
    except OSError as exc:
        print("не могу прочитать header/footer:", exc, file=sys.stderr)
        return 1

    # в превью файлы лежат рядом, а не под /fancyindex_nginx/ на сервере
    header = header.replace('href="/fancyindex_nginx/', 'href="')
    header = header.replace('href="/favicon', 'href="favicon')
    header = header.replace('href="/apple-touch-icon', 'href="apple-touch-icon')

    page = header + build_listing() + footer
    dest = os.path.join(root, "preview.html")
    open(dest, "w", encoding="utf-8").write(page)
    print(f"{dest}  ({len(page)} байт, {len(ENTRIES)} записей)")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
