#!/usr/bin/env python3
"""Auditable recent trading-day dashboard snapshot backfill.

Examples:

  python tools/backfill_recent_snapshots.py --account admin --dry-run
  python tools/backfill_recent_snapshots.py --account admin --lookback 60
  python tools/backfill_recent_snapshots.py --account admin --end-date 2026-08-27 --force
"""

from __future__ import annotations

import argparse
import json
import sys
from datetime import date
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
if str(ROOT) not in sys.path:
    sys.path.insert(0, str(ROOT))

from backend.application import SERVICE
from backend.bootstrap.config import normalize_date
from backend.features.market.backfill_history import DEFAULT_RECENT_TRADING_DAYS


def main() -> None:
    parser = argparse.ArgumentParser(
        description="Backfill the latest N real trading-day dashboard snapshots"
    )
    parser.add_argument(
        "--account",
        required=True,
        help="Account that can resolve the shared Tushare token",
    )
    parser.add_argument(
        "--end-date",
        default=date.today().isoformat(),
        help="Inclusive end date YYYY-MM-DD (default: today)",
    )
    parser.add_argument(
        "--lookback",
        type=int,
        default=DEFAULT_RECENT_TRADING_DAYS,
        help=f"Number of open trading days to cover (default {DEFAULT_RECENT_TRADING_DAYS}, max 60)",
    )
    parser.add_argument(
        "--dry-run",
        action="store_true",
        help="Plan only: classify missing gaps without writing",
    )
    parser.add_argument(
        "--force",
        action="store_true",
        help="Re-sync days that already have snapshots",
    )
    parser.add_argument(
        "--no-backup",
        action="store_true",
        help="Skip the SQLite backup API step (not recommended)",
    )
    parser.add_argument(
        "--json",
        action="store_true",
        help="Print the full audit payload as JSON",
    )
    args = parser.parse_args()

    user = SERVICE.database.user_by_username(args.account.strip())
    if not user:
        raise SystemExit("account not found")
    SERVICE.bind_user(int(user["id"]))

    end_date = normalize_date(args.end_date)
    audit = SERVICE.backfill_recent_trading_days(
        end_date=end_date,
        lookback=args.lookback,
        dry_run=args.dry_run,
        force=args.force,
        create_backup=not args.no_backup,
    )

    if args.json:
        print(json.dumps(audit, ensure_ascii=False, indent=2))
        raise SystemExit(0 if audit.get("ok") else 1)

    print(
        f"mode={audit['mode']} end={audit['end_date']} lookback={audit['lookback']} "
        f"dry_run={audit['dry_run']}"
    )
    print(
        f"present={audit['present_count']} missing={audit['missing_count']} "
        f"succeeded={audit['succeeded_count']} skipped={audit['skipped_count']} "
        f"failed={audit['failed_count']}"
    )
    if audit.get("backup_path"):
        print(f"backup={audit['backup_path']}")
    if audit.get("missing"):
        print("missing_dates=" + ",".join(audit["missing"]))
    if audit.get("created_dates"):
        print("created_dates=" + ",".join(audit["created_dates"]))
    failed = [row for row in audit.get("results") or [] if row.get("status") == "failed"]
    for row in failed:
        print(f"failed {row.get('requested_date')}: {row.get('error')}")
    if not audit.get("ok"):
        raise SystemExit(1)
    print("backfill complete")


if __name__ == "__main__":
    main()
