"""Display properties.json locally. Python standard library only; no API requests."""
import argparse
import json
from html import escape
from http.server import BaseHTTPRequestHandler, HTTPServer
from pathlib import Path

COLUMNS = [("input_id", "Input ID"), ("input_address", "Requested address"),
           ("address", "Returned address"), ("unit", "Unit"), ("status", "Lookup"),
           ("home_status", "Listing status"), ("currency", "Currency"),
           ("price", "Listed price / monthly rent"), ("zestimate", "Zillow Zestimate"),
           ("rent_zestimate", "Zillow monthly rent estimate"), ("beds", "Beds"),
           ("baths", "Baths"), ("living_area", "Area (sq ft)"),
           ("fetched_at", "Collected at"), ("cached", "Cached response"),
           ("review_required", "Review flag"), ("error_code", "Error")]


def cell(value):
    if value is None:
        return "Unavailable"
    if isinstance(value, bool):
        return "Yes" if value else "No"
    return escape(str(value))


def render(snapshot, listing_status="ALL"):
    all_rows = snapshot["rows"]
    rows = [r for r in all_rows if listing_status == "ALL" or r.get("home_status") == listing_status]
    options = "".join(f'<option value="{s}"{" selected" if s == listing_status else ""}>{s}</option>'
                      for s in ["ALL", "FOR_SALE", "FOR_RENT", "RECENTLY_SOLD", "OTHER"])
    head = "".join(f'<th scope="col">{label}</th>' for _, label in COLUMNS)
    body = "".join("<tr>" + "".join(f"<td>{cell(r.get(key))}</td>" for key, _ in COLUMNS) + "</tr>" for r in rows)
    review_count = sum(r.get("review_required") is not False or r.get("status") != "ok" for r in all_rows)
    return f'''<!doctype html><html lang="en"><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Property research snapshot</title><style>
body{{font:16px/1.5 system-ui;margin:2rem;color:#17372b;background:#f5f6f1}}
h1{{line-height:1.2}}select,button{{font:inherit;padding:.5rem}}.table{{overflow:auto}}
table{{border-collapse:collapse;background:white}}td,th{{padding:.8rem;border:1px solid #ccd5cc;text-align:left;min-width:8rem}}
th{{background:#e6eee5}}:focus-visible{{outline:3px solid #246c4e;outline-offset:3px}}
</style><main><h1>Property research snapshot</h1>
<p>{len(all_rows)} submitted rows. {review_count} flagged for review. Showing {len(rows)}.</p>
<p>Exported: {cell(snapshot.get("exported_at"))}. Collection time is shown separately for each property.</p>
<form><label>Listing status <select name="status">{options}</select></label> <button>Filter</button></form>
<p>Listed price means monthly asking rent only for FOR_RENT rows. Estimates are Zillow's, when available.
Review returned addresses and units before using this snapshot. A missing review flag is not an appraisal or a verification of the listing.</p>
<div class="table" tabindex="0" role="region" aria-label="Property comparison"><table><thead><tr>{head}</tr></thead><tbody>{body}</tbody></table></div>
<p>Refreshing this page rereads the local snapshot. It does not make API calls.</p></main></html>'''


def handler_for(snapshot_path):
    class Handler(BaseHTTPRequestHandler):
        def do_GET(self):
            from urllib.parse import parse_qs, urlsplit
            url = urlsplit(self.path)
            if url.path != "/":
                self.send_error(404)
                return
            try:
                snapshot = json.loads(Path(snapshot_path).read_text(encoding="utf-8"))
                html = render(snapshot, parse_qs(url.query).get("status", ["ALL"])[0])
            except (OSError, ValueError, KeyError, TypeError):
                self.send_error(503, "Snapshot unavailable; generate properties.json first")
                return
            content = html.encode("utf-8")
            self.send_response(200)
            self.send_header("Content-Type", "text/html; charset=utf-8")
            self.send_header("Content-Length", str(len(content)))
            self.send_header("Cache-Control", "no-store")
            self.send_header("X-Content-Type-Options", "nosniff")
            self.send_header("Content-Security-Policy", "default-src 'none'; style-src 'unsafe-inline'; form-action 'self'; frame-ancestors 'none'")
            self.end_headers()
            self.wfile.write(content)

        def log_message(self, *args):
            pass
    return Handler


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("snapshot", help="Path to properties.json")
    parser.add_argument("--port", type=int, default=8080)
    args = parser.parse_args()
    server = HTTPServer(("127.0.0.1", args.port), handler_for(args.snapshot))
    print(f"Dashboard: http://127.0.0.1:{args.port} (Ctrl+C to stop)")
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        pass
    finally:
        server.server_close()
