from __future__ import annotations

import argparse
import json
from pathlib import Path
from typing import Any

from src.ctb_copy.read_only_guard import DEFAULT_READ_ONLY_GUARD
from src.ctb_copy.runtime_paths import CopyResearchPaths, day_string, ensure_runtime_dirs
from src.ctb_copy.shadow.position_engine import _extract_asset_positions, run_shadow_engine_once, summarize_shadow_run
from src.ctb_copy.shadow.position_journal import write_shadow_result


def _load_wallet_snapshot_rows(path: Path) -> list[dict[str, Any]]:
    if not path.exists():
        return []
    return [json.loads(line) for line in path.read_text(encoding="utf-8").splitlines() if line.strip()]


def _latest_comparable_wallet_rows(path: Path) -> tuple[list[dict[str, Any]], list[dict[str, Any]]] | None:
    rows = _load_wallet_snapshot_rows(path)
    by_wallet: dict[str, list[dict[str, Any]]] = {}
    for row in rows:
        wallet = str(row.get("wallet_address") or row.get("leader_id") or "")
        if not wallet:
            continue
        by_wallet.setdefault(wallet.lower(), []).append(row)
    previous: list[dict[str, Any]] = []
    current: list[dict[str, Any]] = []
    for wallet_rows in by_wallet.values():
        if len(wallet_rows) >= 2:
            previous.append(wallet_rows[-2])
            current.append(wallet_rows[-1])
    if not previous and not current:
        return None
    return previous, current


def main(argv: list[str] | None = None) -> int:
    parser = argparse.ArgumentParser(description="Run one read-only shadow position engine pass.")
    parser.add_argument("--runtime-dir", default=str(CopyResearchPaths().root))
    parser.add_argument("--day", default=None)
    args = parser.parse_args(argv)

    DEFAULT_READ_ONLY_GUARD.assert_safe()
    paths = CopyResearchPaths(Path(args.runtime_dir))
    day = args.day or day_string()
    ensure_runtime_dirs(paths, day)
    wallet_snapshot_path = paths.snapshot_file("wallets", day)
    rows = _latest_comparable_wallet_rows(wallet_snapshot_path)
    if rows is None:
        status = "ok_no_wallet_snapshots" if not wallet_snapshot_path.exists() else "ok_no_position_deltas"
        summary = summarize_shadow_run(day, [], paths, status=status)
        write_shadow_result(summary, paths.shadow_result_file(day))
        print(json.dumps(summary.to_json_dict(), indent=2, sort_keys=True))
        return 0

    previous_positions = [position for row in rows[0] for position in _extract_asset_positions(row)]
    current_positions = [position for row in rows[1] for position in _extract_asset_positions(row)]
    if not previous_positions and not current_positions:
        summary = summarize_shadow_run(day, [], paths, status="ok_no_position_deltas")
        write_shadow_result(summary, paths.shadow_result_file(day))
        print(json.dumps(summary.to_json_dict(), indent=2, sort_keys=True))
        return 0

    summary = run_shadow_engine_once(previous_positions, current_positions, paths, day=day)
    print(json.dumps(summary.to_json_dict(), indent=2, sort_keys=True))
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
