#!/usr/bin/env python3
"""
Project wrapper: runs the 1688-bp-watch-odm recipe for this project.

This is a thin layer. All recipe logic (keywords, classifier, schema) lives
in `~/.openclaw/apify/recipes/1688_bp_watch_odm.py`. This script just:

  1. Sets the project name so datasets/logs go under the right subdir.
  2. Inherits the next free lead_id (L001, L002, …) from the existing
     stage1_raw_leads.csv in this project, so successive runs continue
     the numbering.
  3. After the run, copies the normalized CSV into the project's local
     stage1_raw_leads.csv (overwriting) so the rest of the project tooling
     (pneumatic-wrist-leads.html, leads.csv merge, etc.) keeps working.

Usage:
    export APIFY_TOKEN=***}
    python3 apify_run.py [--max-cost USD] [--dry-run]

Equivalent to running:
    apify run 1688-bp-watch-odm --project pneumatic-wrist-leads \\
        --max-cost 0.50

…with the lead_id continuation and the project-CSV sync done in Python
because the CLI doesn't know about this project's lead_id sequence.
"""

import argparse
import re
import shutil
import subprocess
import sys
from pathlib import Path

PROJECT = Path(__file__).resolve().parent
PROJECT_CSV = PROJECT / "stage1_raw_leads.csv"
RECIPE = "1688-bp-watch-odm"
PROJECT_NAME = "pneumatic-wrist-leads"


def existing_lead_ids() -> set[str]:
    if not PROJECT_CSV.exists():
        return set()
    ids = set()
    with PROJECT_CSV.open(encoding="utf-8") as f:
        for line in f:
            m = re.match(r"^L\d{3}", line)
            if m:
                ids.add(m.group(0))
    return ids


def find_latest_run_csv() -> Path | None:
    """Locate the most recent normalized.csv under ~/.openclaw/apify/datasets."""
    base = Path.home() / ".openclaw/apify" / "datasets" / PROJECT_NAME / RECIPE
    if not base.exists():
        return None
    runs = sorted([p for p in base.iterdir() if p.is_dir()], reverse=True)
    for r in runs:
        csv = r / "stage1_raw_leads.csv"
        if csv.exists():
            return csv
    return None


def main() -> int:
    ap = argparse.ArgumentParser()
    ap.add_argument("--max-cost", type=float, default=0.50)
    ap.add_argument("--dry-run", action="store_true")
    ap.add_argument("--no-sync", action="store_true",
                    help="don't copy the new CSV into the project dir")
    args = ap.parse_args()

    # Pass --max-cost through to the CLI; the recipe's default is 0.50 anyway.
    cli = ["/home/claw/bin/apify", "run", RECIPE.replace("_", "-"),
           "--project", PROJECT_NAME, "--max-cost", str(args.max_cost)]
    if args.dry_run:
        cli.append("--dry-run")
    print(f"$ {' '.join(cli)}", flush=True)
    rc = subprocess.call(cli)
    if rc != 0:
        return rc
    if args.dry_run or args.no_sync:
        return 0

    latest = find_latest_run_csv()
    if not latest:
        print("warning: no run output found; skipping sync", file=sys.stderr)
        return 0

    # Append-mode sync: load existing project lead_ids, then append only rows
    # whose lead_id is new (the recipe assigns L001, L002, … starting from
    # 1; we adjust them to continue from the highest existing L### here).
    import csv as _csv
    existing_ids = existing_lead_ids()
    new_rows: list[dict] = []
    next_id_n = 1
    while f"L{next_id_n:03d}" in existing_ids:
        next_id_n += 1
    with latest.open(encoding="utf-8") as f:
        for r in _csv.DictReader(f):
            new_id = f"L{next_id_n:03d}"
            next_id_n += 1
            r["lead_id"] = new_id
            new_rows.append(r)
    if not new_rows:
        print("no new rows; project CSV untouched.")
        return 0

    cols = list(new_rows[0].keys())
    write_header = not PROJECT_CSV.exists()
    with PROJECT_CSV.open("a", newline="", encoding="utf-8") as f:
        w = _csv.DictWriter(f, fieldnames=cols, extrasaction="ignore")
        if write_header:
            w.writeheader()
        for r in new_rows:
            w.writerow(r)
    print(f"synced {len(new_rows)} new rows to {PROJECT_CSV} "
          f"(continuing from L{next_id_n - len(new_rows):03d})")
    return 0


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