from __future__ import annotations import argparse from datetime import datetime from app.config import configure_logging, get_settings from app.db import init_db, session_scope from app.inbox_locks import inbox_run_locks from app.message_processor import process_inbox def _date(value: str | None): return datetime.strptime(value, "%Y-%m-%d").date() if value else None def backlog(args: argparse.Namespace) -> int: settings = get_settings() configure_logging(settings) init_db() inbox = settings.get_inbox(args.inbox) lease = inbox_run_locks.acquire(inbox.id, blocking=False) if not lease: print(f"Inbox {inbox.id} is already processing.") return 1 with session_scope() as session: with lease: summary = process_inbox( session, settings, inbox, folder=args.folder or inbox.folder, mode="backlog", since=_date(args.since), before=_date(args.before), limit=args.limit, dry_run=args.dry_run, reprocess=args.reprocess, mark_seen=args.mark_seen, ) print("Backlog run complete") print(f"Inbox: {summary.inbox_id}") print(f"Folder: {summary.folder}") print(f"Scanned messages: {summary.scanned_messages}") print(f"Candidate messages: {summary.candidate_messages}") print(f"Valid reports imported: {summary.valid_reports_imported}") print(f"Duplicate messages skipped: {summary.duplicate_messages_skipped}") print(f"Duplicate report payloads skipped: {summary.duplicate_reports_skipped}") print(f"Rejected messages: {summary.rejected_messages}") print(f"Failed messages: {summary.failed_messages}") print(f"Records imported: {summary.records_imported}") print(f"Alerts created: {summary.alerts_created}") print(f"LLM explanations generated: {summary.llm_explanations_generated}") return 0 def build_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser(prog="python -m app.cli") sub = parser.add_subparsers(dest="command", required=True) backlog_parser = sub.add_parser("backlog") backlog_parser.add_argument("--inbox", required=True) backlog_parser.add_argument("--folder") backlog_parser.add_argument("--since") backlog_parser.add_argument("--before") backlog_parser.add_argument("--limit", type=int, default=500) backlog_parser.add_argument("--dry-run", action="store_true") backlog_parser.add_argument("--reprocess", action="store_true") backlog_parser.add_argument("--mark-seen", action="store_true") backlog_parser.set_defaults(func=backlog) return parser def main() -> int: parser = build_parser() args = parser.parse_args() return args.func(args) if __name__ == "__main__": raise SystemExit(main())