from pathlib import Path
import hashlib, orjson, os
from typing import Dict, List

OUTPUT_DIR = Path(os.getenv("OUTPUT_DIR", "./out"))

CANON_FIELDS = ["broker", "listing_id", "price", "points", "status"]

def _hash_row(row: Dict) -> str:
    s = "|".join(str(row.get(k, "")) for k in CANON_FIELDS)
    return hashlib.sha256(s.encode("utf-8")).hexdigest()

def _read_jsonl(path: Path) -> List[Dict]:
    if not path.exists():
        return []
    return [orjson.loads(line) for line in path.read_bytes().splitlines()]

def produce_changes():
    latest_dir = OUTPUT_DIR / "latest"
    # last combined as "previous" snapshot
    prev_combined = latest_dir / "combined.jsonl"
    # current snapshot = today directory merged
    today_dirs = sorted([p for p in OUTPUT_DIR.iterdir() if p.is_dir() and p.name[:1].isdigit()])
    if not today_dirs:
        return 0
    today_dir = today_dirs[-1]

    curr_rows: List[Dict] = []
    for p in today_dir.glob("*.jsonl"):
        curr_rows += _read_jsonl(p)
    prev_rows = _read_jsonl(prev_combined)

    prev_map = {(r.get("broker"), r.get("listing_id")): _hash_row(r) for r in prev_rows if r.get("listing_id")}
    curr_map = {(r.get("broker"), r.get("listing_id")): _hash_row(r) for r in curr_rows if r.get("listing_id")}

    changes = []
    prev_keys, curr_keys = set(prev_map), set(curr_map)
    for k in curr_keys - prev_keys:
        changes.append({"change_type": "added", "key": k})
    for k in prev_keys - curr_keys:
        changes.append({"change_type": "removed", "key": k})
    for k in curr_keys & prev_keys:
        if curr_map[k] != prev_map[k]:
            changes.append({"change_type": "updated", "key": k})

    out = latest_dir / "changes.jsonl"
    with out.open("wb") as f:
        for c in changes:
            f.write(orjson.dumps(c) + b"\n")
    return len(changes)
