import logging
from pytz import timezone

from dateutil.relativedelta import relativedelta


LOG = logging.getLogger(__name__)


class Subscription(object):

    title = None
    purchase_date = None
    first_issue = None
    last_issue = None
    duration = None

    # servers are eastern time, force this setting
    eastern = timezone("US/Eastern")

    def __init__(self, title, start_date, duration):

        self.title = title
        self.purchase_date = start_date.replace(tzinfo=self.eastern)
        self.duration = duration
        self.first_issue = self._calculate_first_issue(self.purchase_date)
        self.last_issue = self._calculate_last_issue(self.first_issue, duration)

    @staticmethod
    def _calculate_first_issue(start_date):
        """
        Our cutoff is Wed. at 8 a.m., but for simplicity and to make sure
        everything gets processed, lets cut it off at the end of the day Tues.
        So the subscription date runs for the time frame ordered from the next
        Thursday. After Tuesday, it gets filled on the following week.
        """
        tuesday = 1
        thursday_offset = 2
        week_offset = 7

        days_till_tuesday = tuesday - start_date.weekday()
        LOG.debug(
            "days till tuesday: {0} = {1} - {2}".format(
                days_till_tuesday, tuesday, start_date.weekday()
            )
        )

        # apply the days till tuesday plus the thursday offset, this may be
        # negative
        thursday = start_date + relativedelta(days=days_till_tuesday + thursday_offset)
        LOG.debug("Thursday calculated to be: {0}".format(thursday))

        if thursday < start_date:
            thursday += relativedelta(days=week_offset)
            LOG.debug("Thursday adjusted to: {0}".format(thursday))

        return thursday

    @staticmethod
    def _calculate_last_issue(first_issue, duration):
        thursday = 3

        # apply
        last_issue = first_issue + relativedelta(months=duration)

        # re-adjust the day to the closest thursday
        days_till_thursday = thursday - last_issue.weekday()
        last_issue += relativedelta(days=days_till_thursday)

        return last_issue

    def extend_subscription(self, duration):
        self.duration += duration
        self.end_date = self._calculate_last_issue(self.purchase_date, self.duration)

    def within_subscription(self, title, date):
        date = date.replace(tzinfo=self.eastern)
        LOG.debug(
            "Checking {0} with {1} for between {2} and {3}".format(
                title, date, self.purchase_date, self.last_issue
            )
        )
        return self.title == title and self.purchase_date <= date <= self.last_issue

    @classmethod
    def is_within_subscription(cls, subscriptions, order_item):
        for subscription in subscriptions:
            if subscription.within_subscription(
                order_item.product.title, order_item.order.date
            ):
                return subscription
        return None
