"""
prune.py — Keep the top X entries in a leaderboard, delete the rest.

Entries are ranked by score descending. On score ties at the boundary,
the newest entries (by created timestamp) are kept and the oldest are removed.

Usage:
    py scripts/prune.py <leaderboard> <limit>           # prompts for confirmation
    py scripts/prune.py <leaderboard> <limit> --yes     # skips confirmation (for cron/automation)

Examples:
    py scripts/prune.py global 1000
    py scripts/prune.py daily 500 --yes

Leaderboards: global, weekly, daily
"""

import argparse
import sys
import os

# Allow imports from the project root regardless of where this script is invoked from
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from app import create_app
from models import db, LEADERBOARD_MAP


def main():
    parser = argparse.ArgumentParser(
        description="Keep the top X entries in a leaderboard by score, delete the rest.",
        epilog="Example: py scripts/prune.py global 1000 --yes",
    )
    parser.add_argument(
        "leaderboard",
        choices=LEADERBOARD_MAP.keys(),
        help="The leaderboard to prune (global, weekly, daily).",
    )
    parser.add_argument(
        "limit",
        type=int,
        help="Number of top entries to keep. Must be a positive integer.",
    )
    parser.add_argument(
        "--yes",
        action="store_true",
        help="Skip the confirmation prompt. Required for non-interactive use (e.g. cron).",
    )
    args = parser.parse_args()

    if args.limit < 1:
        parser.error("limit must be a positive integer.")

    if not args.yes:
        confirm = input(
            f"This will delete all entries in '{args.leaderboard}' outside the top {args.limit}. "
            "Type 'yes' to continue: "
        )
        if confirm.strip().lower() != "yes":
            print("Aborted.")
            sys.exit(0)

    app = create_app()
    with app.app_context():
        model = LEADERBOARD_MAP[args.leaderboard]

        # Collect IDs of entries to keep: top <limit> by score, newest wins ties
        keep_ids = [
            row.id
            for row in db.session.query(model.id)
            .order_by(model.score.desc(), model.created.desc())
            .limit(args.limit)
            .all()
        ]

        if len(keep_ids) < args.limit:
            print(
                f"'{args.leaderboard}' has {len(keep_ids)} entries, which is under the limit of {args.limit}. "
                "Nothing to prune."
            )
            sys.exit(0)

        pruned = (
            db.session.query(model)
            .filter(model.id.not_in(keep_ids))
            .delete(synchronize_session="fetch")
        )
        db.session.commit()
        print(f"Pruned {pruned} entries from '{args.leaderboard}'. {len(keep_ids)} entries remain.")


if __name__ == "__main__":
    main()
