"""
Release auction reservations that were never completed.

A reservation holds a listing for five working days. Without this the hold only
lifts when somebody happens to open the page, so an abandoned reservation can
keep a name off the market indefinitely.

Run hourly from cron:

    0 * * * * cd /home/<user>/public_html/backend && \
      venv/bin/python manage.py release_reservations --settings=config.settings.production
"""
from django.core.management.base import BaseCommand
from django.utils import timezone

from apps.ecommerce.models import Product


class Command(BaseCommand):
    help = 'Return lapsed auction reservations to Available.'

    def add_arguments(self, parser):
        parser.add_argument(
            '--dry-run', action='store_true',
            help='Show what would be released without changing anything.',
        )

    def handle(self, *args, **options):
        from apps.ftlink.models import JobRun
        dry = options['dry_run']
        now = timezone.now()

        lapsed = Product.objects.filter(
            auction_status=Product.AUCTION_RESERVED,
            reserved_until__lt=now,
        )

        count = 0
        for p in lapsed:
            held_by = p.reserved_order.customer_email if p.reserved_order else 'unknown'
            self.stdout.write(
                f'{"Would release" if dry else "Releasing"}: {p.name} '
                f'(held by {held_by}, lapsed {p.reserved_until:%d %b %Y %H:%M})'
            )
            if not dry:
                p.auction_status = Product.AUCTION_AVAILABLE
                p.reserved_until = None
                # reserved_order is kept: the fee was genuinely paid and the
                # order must stay in the books even though the hold has gone.
                p.save(update_fields=['auction_status', 'reserved_until'])
            count += 1

        if count:
            self.stdout.write(self.style.SUCCESS(f'{count} reservation(s) {"to release" if dry else "released"}.'))
        else:
            self.stdout.write('No reservations have lapsed.')
        if not dry:
            JobRun.record('release_reservations', note=f'{count} released')
