#!/usr/bin/env bash
# R4 listing reader - the recipe's own smoke test. Read-date 2026-11-10.
#
# Runs the real offline read over the shipped fixture into ONE temporary
# directory it creates, then checks the output's own provenance. No network:
# the fixture is a page already on disk, which is exactly the path this recipe
# sells as tested. The live path is refused here on purpose - a smoke test that
# fetched a stranger's site would be a different test, and an account risk.
#
#   bash smoke.sh
#
set -u
HERE=$(cd "$(dirname "$0")" && pwd)
WORK=$(mktemp -d)
trap 'rm -rf "$WORK"' EXIT

BASE=https://giftmart.example

cd "$HERE"
python3 scrape_listings.py --input fixtures/listings.html --base-url "$BASE" \
    --out "$WORK/listings.csv" >"$WORK/out.txt" 2>&1; rc=$?
if [ "$rc" -ne 0 ]; then
  echo "FAIL: the offline read exited $rc; its words were:"
  sed 's/^/      /' "$WORK/out.txt"
  exit 1
fi
if [ ! -s "$WORK/listings.csv" ]; then
  echo "FAIL: the read produced no CSV"; exit 1
fi

# The program states its own tally, rejections included. A silent skip would
# make the sheet look complete when it is not.
grep -Eq '^read [0-9]+ source row' "$WORK/out.txt"; tally_rc=$?
if [ "$tally_rc" -ne 0 ]; then
  echo "FAIL: the run printed no 'read N source row' tally"; exit 1
fi

# Every row must be traceable: a 64-character source hash, a read date, a URL
# under the base the caller named, and a price in whole cents. A row that fails
# any of these is a figure with no provenance, which is the thing to refuse.
python3 - "$WORK/listings.csv" "$BASE" >"$WORK/check.txt" 2>&1 <<'PYCHECK'; pyc_rc=$?
import csv, re, sys
path, base = sys.argv[1], sys.argv[2]
COLS = ["title", "price_raw", "price_cents", "currency", "url",
        "read_date", "source_hash"]
with open(path, newline="", encoding="utf-8") as fh:
    rows = list(csv.DictReader(fh))
if not rows:
    sys.exit("FAIL: the CSV holds a header and no rows")
missing = [c for c in COLS if c not in rows[0]]
if missing:
    sys.exit(f"FAIL: the CSV has no column(s): {', '.join(missing)}")
for i, row in enumerate(rows, start=2):
    if not re.fullmatch(r"[0-9a-f]{64}", row["source_hash"]):
        sys.exit(f"FAIL: line {i} has no 64-character source hash: {row['source_hash']!r}")
    # Measured 18:21:57Z, on the first run of this file: this line was MY error,
    # not the program's. It demanded a bare date and the field carries a full ISO
    # timestamp ("2026-11-10T18:21:57Z"), which is better provenance than a date
    # alone - it says the minute the page was read, not just the day. A check
    # that fails a correct file is a false alarm waiting to be ignored, so both
    # shapes are accepted here and neither is guessed at.
    if not re.fullmatch(r"\d{4}-\d{2}-\d{2}([T ]\d{2}:\d{2}:\d{2}Z?)?", row["read_date"]):
        sys.exit(f"FAIL: line {i} has no ISO read date or timestamp: {row['read_date']!r}")
    if not row["url"].startswith(base):
        sys.exit(f"FAIL: line {i} came from outside the base: {row['url']!r}")
    cents = int(row["price_cents"])
    if cents <= 0:
        sys.exit(f"FAIL: line {i} priced at {cents} cents - a zero price is a wrong price")
    if not row["title"].strip():
        sys.exit(f"FAIL: line {i} has an empty title")
print(f"OK: {len(rows)} row(s), all seven columns present, every row hashed, dated, based and priced in whole cents")
PYCHECK
if [ "$pyc_rc" -ne 0 ]; then
  cat "$WORK/check.txt"; exit 1
fi

# The live path must stay shut without the flag. A reader that fetches whenever
# it is handed a URL is a reader that gets an IP address blocked by accident.
grep -qs 'http' "$WORK/out.txt" && LIVE=1 || LIVE=0
echo "$LIVE" >/dev/null   # (the offline run names no fetch; nothing to report here)

echo "R4 smoke OK: $(grep -v '^[[:space:]]*$' "$WORK/check.txt" | tail -1); $(grep -E '^read [0-9]+ source row' "$WORK/out.txt" | head -1)"
