#!/usr/bin/env python3
"""Re-checks every value in the embed-photo-album-website table and fact list.

Fetches each cited help page, extracts its readable text, and asserts the exact
supporting sentence still appears. Also asserts that the two pages whose row says
"no embed code" still contain neither "embed" nor "iframe". Product facts are checked
against the repository source at the paths recorded in dataset.json.

Exits 0 when everything holds, 1 otherwise. `--recheck` re-reads the pages and skips
no step shorter than a minute (none here are longer).
"""

from __future__ import annotations

import argparse
import html
import json
import re
import sys
import urllib.request
from pathlib import Path

HERE = Path(__file__).resolve().parent
REPO_ROOT = HERE.parents[4]
DATASET = HERE / "dataset.json"
UA = (
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
    "(KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36"
)
HEADERS = {
    "User-Agent": UA,
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.9",
    "Sec-Fetch-Mode": "navigate",
    "Sec-Fetch-Site": "none",
    "Sec-Fetch-Dest": "document",
    "Upgrade-Insecure-Requests": "1",
}
TIMEOUT = 30


def fetch(url: str) -> str:
    request = urllib.request.Request(url, headers=HEADERS)
    with urllib.request.urlopen(request, timeout=TIMEOUT) as response:
        return response.read().decode("utf-8", errors="replace")


def readable_text(source: str) -> str:
    source = re.sub(r"<script.*?</script>|<style.*?</style>", " ", source, flags=re.S)
    source = re.sub(r"<[^>]+>", " ", source)
    source = html.unescape(source)
    return normalise(source)


def normalise(text: str) -> str:
    text = re.sub(r"\s+", " ", text)
    return re.sub(r"\s+([.,;:])", r"\1", text).strip()


def page_text(entry: dict) -> str:
    """The citable text of an input. Flickr's article arrives as JSON from its help centre."""
    body = fetch(entry["fetchUrl"] if "fetchUrl" in entry else entry["url"])
    if entry.get("format") == "zendesk-json":
        article = json.loads(body)["article"]
        return normalise(f"{article.get('title', '')} {readable_text(article.get('body', ''))}")
    return readable_text(body)


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--recheck",
        action="store_true",
        help="re-read the cited pages (the normal run does this too; no lab step here exceeds a minute)",
    )
    parser.parse_args()

    data = json.loads(DATASET.read_text(encoding="utf-8"))
    inputs = {entry["id"]: entry for entry in data["inputs"]}
    pages: dict[str, str] = {}
    failures: list[str] = []

    def text_for(input_id: str) -> str:
        if input_id not in pages:
            pages[input_id] = page_text(inputs[input_id])
        return pages[input_id]

    for row in data["results"]:
        print(f"\n{row['option']}")
        for evidence in row["evidence"]:
            source = evidence.get("input") or evidence.get("path")
            if "path" in evidence:
                raw = (REPO_ROOT / evidence["path"]).read_text(encoding="utf-8")
                haystack = normalise(raw)
                label = evidence["path"]
            else:
                haystack = text_for(evidence["input"])
                label = inputs[evidence["input"]]["url"]
            ok = normalise(evidence["quote"]) in haystack
            print(f"  {'OK  ' if ok else 'FAIL'} {evidence['property']}: {label}")
            if not ok:
                failures.append(f"{row['option']} / {evidence['property']}: quote gone from {label}")

    for fact in data.get("facts", []):
        print(f"\nfact: {fact['label']}")
        for evidence in fact["evidence"]:
            if "path" in evidence:
                raw = (REPO_ROOT / evidence["path"]).read_text(encoding="utf-8")
                haystack = normalise(raw)
                label = evidence["path"]
            else:
                haystack = text_for(evidence["input"])
                label = inputs[evidence["input"]]["url"]
            ok = normalise(evidence["quote"]) in haystack
            print(f"  {'OK  ' if ok else 'FAIL'} {label}")
            if not ok:
                failures.append(f"{fact['label']}: quote gone from {label}")

    print("\nabsence checks")
    for check in data.get("absent", []):
        text = text_for(check["input"]).lower()
        found = [term for term in check["terms"] if term in text]
        ok = not found
        print(
            f"  {'OK  ' if ok else 'FAIL'} {inputs[check['input']]['url']}: "
            f"no {' / '.join(check['terms'])}" + (f" (found {found})" if found else "")
        )
        if not ok:
            failures.append(
                f"{inputs[check['input']]['url']}: now mentions {found}; re-read before keeping the 'No' cell"
            )

    print()
    if failures:
        for failure in failures:
            print(f"FAIL {failure}")
        return 1
    print("all checks hold")
    return 0


if __name__ == "__main__":
    sys.exit(main())
