#!/usr/bin/env python3
"""
Fix / reset tracking data in MCRO JSON files using tracking_new.csv,
supporting MULTIPLE pdf_groups per document.

BEHAVIOR (THIS VERSION)
=======================

  • tracking_new.csv is keyed by *PDF filename* (column: 'filename').

  • A given filename may appear in tracking_new.csv MULTIPLE times – each row
    is one pdf_group/font_group definition for that document.

  • For EVERY *.json file in --json-dir:
      1. Wipe the entire "tracking" object:
           data["tracking"] = {}

      2. Look up ALL rows in tracking_new.csv with matching 'filename'
         == data["filename"].

         - If at least one row is found:
             tracking.tracked_flag = true
             tracking.groups = [
                 { <all tracking columns from row 1 except 'filename'> },
                 { <all tracking columns from row 2 except 'filename'> },
                 ...
             ]

         - If no row is found:
             tracking.tracked_flag = false
             tracking.groups = []   (empty list for consistency)

  • After processing all JSON files, print a summary to the CLI of:
        - tracked_flag true / false counts
        - Total number of group entries
        - Unique pdf_group values and how many group entries ended up in each.

Usage:
  python3 mcro_tracking_fix.py \
      --json-dir "/path/to/json_dir" \
      --csv "tracking_new.csv"

If you omit --json-dir, it defaults to the current directory.
If you omit --csv, it defaults to "tracking_new.csv" in the current directory.
"""

import argparse
import csv
import json
from pathlib import Path
from typing import Dict, Any, List
import sys


def load_tracking_csv(csv_path: Path):
    """
    Load tracking_new.csv into:
      - mapping: filename -> list of row dicts
      - cols: list of column names (so we know which keys to write under each group)

    Each row in the CSV corresponds to ONE group definition for that filename.
    """
    if not csv_path.is_file():
        raise FileNotFoundError(f"tracking CSV not found: {csv_path}")

    with csv_path.open("r", newline="", encoding="utf-8") as f:
        reader = csv.DictReader(f)
        fieldnames = reader.fieldnames or []
        if "filename" not in fieldnames:
            raise ValueError("tracking_new.csv must contain a 'filename' column")

        rows = list(reader)

    mapping: Dict[str, List[Dict[str, Any]]] = {}
    for row in rows:
        fn = (row.get("filename") or "").strip()
        if not fn:
            continue
        mapping.setdefault(fn, []).append(row)

    # All CSV columns except 'filename' become tracking subkeys within each group
    tracking_cols = [c for c in fieldnames if c != "filename"]

    return mapping, tracking_cols


def main():
    parser = argparse.ArgumentParser(
        description="Reset and repopulate tracking.* in MCRO JSON files (keyed by filename, multiple groups per doc)."
    )
    parser.add_argument(
        "--json-dir",
        default=".",
        help="Directory containing JSON files (default: current directory)",
    )
    parser.add_argument(
        "--csv",
        default="tracking_new.csv",
        help="Path to tracking_new.csv (default: ./tracking_new.csv)",
    )
    args = parser.parse_args()

    json_dir = Path(args.json_dir)
    csv_path = Path(args.csv)

    if not json_dir.is_dir():
        raise NotADirectoryError(f"JSON directory does not exist: {json_dir}")

    try:
        mapping, tracking_cols = load_tracking_csv(csv_path)
    except Exception as e:
        print(f"[error] Failed to load tracking CSV: {e}", file=sys.stderr)
        sys.exit(1)

    print(f"[info] Loaded tracking rows for {len(mapping)} distinct filenames from {csv_path}")
    print(f"[info] Tracking subkeys for each group: {tracking_cols}")

    json_files = sorted(json_dir.glob("*.json"))
    print(f"[info] Found {len(json_files)} JSON files in {json_dir}")

    # Counters for summary
    n_tracked_true = 0
    n_tracked_false = 0
    total_groups = 0
    pdf_group_counts: Dict[str, int] = {}

    for jp in json_files:
        try:
            text = jp.read_text(encoding="utf-8")
            data = json.loads(text)
        except Exception as e:
            print(f"[warn] Skipping {jp.name}: failed to parse JSON ({e})")
            continue

        # Ensure top-level object is a dict
        if not isinstance(data, dict):
            print(f"[warn] Skipping {jp.name}: JSON root is not a dict")
            continue

        # Pull the PDF filename from the JSON
        json_filename_field = (data.get("filename") or "").strip()
        if not json_filename_field:
            # No filename in JSON = cannot match CSV row
            row_list: List[Dict[str, Any]] = []
        else:
            row_list = mapping.get(json_filename_field, [])

        # 1. Wipe tracking subtree
        data["tracking"] = {}
        tracking = data["tracking"]

        if row_list:
            # 2a. JSON filename is present in tracking_new.csv (one or more rows):
            #     tracked_flag = true + groups = [ {cols from row1}, {row2}, ... ]
            tracking["tracked_flag"] = True
            n_tracked_true += 1

            groups: List[Dict[str, Any]] = []
            for row in row_list:
                g: Dict[str, Any] = {}
                for col in tracking_cols:
                    val = row.get(col)
                    if val is None:
                        continue
                    val_str = str(val)
                    if val_str == "":
                        continue
                    g[col] = val_str
                if g:
                    groups.append(g)

                    # Count pdf_group for summary, if present
                    pg = g.get("pdf_group")
                    if pg is not None and str(pg).strip() != "":
                        pg_str = str(pg).strip()
                        pdf_group_counts[pg_str] = pdf_group_counts.get(pg_str, 0) + 1

            tracking["groups"] = groups
            total_groups += len(groups)

        else:
            # 2b. JSON filename is NOT present in CSV:
            #     only tracked_flag = false, groups = []
            tracking["tracked_flag"] = False
            tracking["groups"] = []
            n_tracked_false += 1

        # Write JSON back out (in-place)
        try:
            jp.write_text(
                json.dumps(data, ensure_ascii=False, indent=2),
                encoding="utf-8",
            )
        except Exception as e:
            print(f"[warn] Failed to write updated JSON for {jp.name}: {e}")
            continue

    # ---- Summary report to CLI ----
    print("\n[summary] Tracking rewrite complete.")
    print(f"  JSON files processed      : {len(json_files)}")
    print(f"  tracked_flag = true       : {n_tracked_true}")
    print(f"  tracked_flag = false      : {n_tracked_false}")
    print(f"  Total group entries (rows): {total_groups}")

    if pdf_group_counts:
        print("\n[summary] pdf_group distribution (across ALL groups):")
        # Sort by pdf_group label; adjust key to sort by count if you prefer
        for pg in sorted(pdf_group_counts.keys()):
            print(f"  pdf_group={pg!r} -> {pdf_group_counts[pg]} group(s)")
        print(f"\n  Total unique pdf_group values: {len(pdf_group_counts)}")
    else:
        print("\n[summary] No pdf_group values were present in any groups.")

    print("[ok] Finished updating tracking.* for all JSON files.")


if __name__ == "__main__":
    main()
