from datetime import date, timedelta

from django.utils.timezone import now
from django.core.management.base import BaseCommand

from users.licenses import MYSKILLBOX_LICENSES
from users.models import License, NO_DATE

YEARLY_ISBNS = ["978-3-0355-1860-3", "978-3-0355-1823-8"]
LONGER_DURATION = 455


class Command(BaseCommand):
    help = """
    Reset licenses that have a duration of one year
    Uses the duration of MYSKILLBOX_LICENSES as reference.
    """

    def add_arguments(self, parser):
        parser.add_argument('--dry-run', action='store_true', dest='dry_run', default=False, help='Make dry-run')

    def handle(self, *args, **options):
        today = now().date()

        for license in License.objects.filter(expire_date__gte=today):
            isbn = license.get_hep_isbn()
            if isbn not in YEARLY_ISBNS:
                continue

            standard_duration = MYSKILLBOX_LICENSES[isbn]['duration']  # use isbn from hep due to our bug
            start_date = license.get_hep_start_date()
            duration_in_days = (license.expire_date - start_date).days
            if duration_in_days == standard_duration:
                continue

            user_join_delta = (license.expire_date - license.licensee.date_joined.date()).days

            if self._is_change_candidate(user_join_delta, duration_in_days, start_date):
                self._update_expiry_date(license, standard_duration, options['dry_run'])

    def _is_change_candidate(self, user_join_delta: int, duration_in_days: int, start_date: date) -> bool:
        """
        user_join_delta == LONGER_DURATION: user joined the same number of days as the old duration was
        duration_in_days == LONGER_DURATION: delta from start date and expiry date is the same as the old duration
        start_date == NO_DATE: license does not have a start date -> was created after moving to new api as
        such it the longer duration was set as duration
        """
        return user_join_delta == LONGER_DURATION or duration_in_days == LONGER_DURATION \
               or start_date == NO_DATE

    def _update_expiry_date(self, license: License, standard_duration: int, dry_run: bool):
        new_expiry_date = license.expire_date - timedelta(LONGER_DURATION - standard_duration)
        user_expire_date = license.licensee.license_expiry_date

        if user_expire_date == license.expire_date:
            print(f'Resetting user expire_date for userID {license.licensee.id} from'
                  f' {license.licensee.license_expiry_date} to {new_expiry_date}')

            if not dry_run:
                license.licensee.license_expiry_date = new_expiry_date
                license.licensee.save()

        print(f'Resetting expiry date for license ID {license.id} ({license.expire_date}) to {new_expiry_date}')

        if not dry_run:
            license.expire_date = new_expiry_date
            license.save()
