from collections import namedtuple
from datetime import timedelta
from decimal import Decimal
from django.conf import settings
from django.contrib.auth.models import Group
from django.core.exceptions import ObjectDoesNotExist
from django.core.management.base import BaseCommand

from registrasion.models import inventory as inv
from registrasion.models import conditions as cond
from symposion import proposals


class Command(BaseCommand):
    help = 'Populates the tickets and product inventory models'
    count = 0

    def add_arguments(self, parser):
        pass

    def handle(self, *args, **options):

        kinds = []
        for i in settings.MAIN_CONFERENCE_PROPOSAL_KINDS:
            kinds.append(proposals.models.ProposalKind.objects.get(name=i))
        self.main_conference_proposals = kinds

        self.populate_groups()
        self.populate_inventory()
        self.populate_restrictions()
        self.populate_discounts()

    def populate_groups(self):
        self.group_team = self.find_or_make(
            Group,
            ("name", ),
            name="Conference organisers",
        )
        self.group_volunteers = self.find_or_make(
            Group,
            ("name", ),
            name="Conference volunteers",
        )
        self.group_unpublish = self.find_or_make(
            Group,
            ("name", ),
            name="Can see unpublished products",
        )
        self.group_prepurchase = self.find_or_make(
            Group,
            ("name", ),
            name="Pre-purchase",
        )

    def populate_inventory(self):
        # Categories

        self.ticket = self.find_or_make(
            inv.Category,
            ("name",),
            name="Ticket",
            description="Each type of ticket has different included products. "
                        "For details of what products are included, see our "
                        "<a href=\"/attend/tickets/\">registration page</a>.",
            required=True,
            render_type=inv.Category.RENDER_TYPE_RADIO,
            limit_per_user=1,
            order=1,
        )
        self.terms = self.find_or_make(
            inv.Category,
            ("name",),
            name="Terms, Conditions, and Code of Conduct Acceptance",
            description="I agree to the "
                        "<a href=\"/attend/terms-and-conditions/\"> "
                        "terms and conditions of attendance</a>, and I have read, "
                        "understood, and agree to act according to the standards set "
                        "forth in our <a href=\"/attend/code-of-conduct/\">"
                        "Code of Conduct</a>.",
            required=True,
            render_type=inv.Category.RENDER_TYPE_CHECKBOX,
            order=10,
        )
        # self.penguin_dinner = self.find_or_make(
        #     inv.Category,
        #     ("name",),
        #     name="Penguin Dinner Ticket",
        #     description="Tickets to our conference dinner on the evening of "
        #                 f"{settings.PENGUIN_DINNER_TICKET_DATE: %A %d %B}. "
        #                 "All attendees may purchase "
        #                 "seats at the dinner, even if a dinner ticket is not "
        #                 "included in your conference ticket price.",
        #     required=False,
        #     render_type=inv.Category.RENDER_TYPE_QUANTITY,
        #     limit_per_user=10,
        #     order=20,
        # )
        # self.speakers_dinner_ticket = self.find_or_make(
        #     inv.Category,
        #     ("name",),
        #     name="Speakers' Dinner Ticket",
        #     description="Tickets to our exclusive Speakers' Dinner on the "
        #                 "evening of "
        #                 f"{settings.SPEAKER_DINNER_TICKET_DATE: %A %d %B}.",
        #     required=False,
        #     render_type=inv.Category.RENDER_TYPE_QUANTITY,
        #     limit_per_user=1,
        #     order=30,
        # )
        # self.pdns_category = self.find_or_make(
        #     inv.Category,
        #     ("name",),
        #     name="Professional Delegates Networking Session Ticket",
        #     description="Tickets to our Professional Delegates Networking session. "
        #                 "This event will be held on the evening of "
        #                 f"{settings.PDNS_TICKET_DATE: %A %d %B} "
        #                 "and is restricted to Professional Ticket "
        #                 "holders, speakers, miniconf organisers, and invited "
        #                 "guests.",
        #     required=False,
        #     render_type=inv.Category.RENDER_TYPE_RADIO,
        #     limit_per_user=1,
        #     order=40,
        # )
        # self.t_shirt = self.find_or_make(
        #     inv.Category,
        #     ("name",),
        #     name="Shirt",
        #     description="Commemorative conference shirts, featuring the "
        #                 f"linux.conf.au {settings.CONF_START.year} artwork. "
        #                 "View the <a href=\"/attend/shirts/\">"
        #                 "sizing guide</a>.",
        #     required=False,
        #     render_type=inv.Category.RENDER_TYPE_ITEM_QUANTITY,
        #     order=50,
        # )
        # self.accommodation = self.find_or_make(
        #     inv.Category,
        #     ("name",),
        #     name="Accommodation at University of Tasmania",
        #     description="Accommodation at the University of Tasmania colleges "
        #                 "and apartments. You can come back and book your "
        #                 "accommodation at a later date, provided rooms remain "
        #                 "available. Rooms may only be booked from Sunday 15 "
        #                 "January--Saturday 21 January. If you wish to stay "
        #                 "for only a part of the 6-day period, you must book "
        #                 "accommodation for the full 6-day period. Rooms at "
        #                 "other hotels, including Wrest Point can be booked "
        #                 "elsewhere. For full details, see [LINK]our "
        #                 "accommodation page.[/LINK]",
        #     required=False,
        #     render_type=inv.Category.RENDER_TYPE_RADIO,
        #     limit_per_user=1,
        #     order=50,
        # )
        self.badge_category = self.find_or_make(
            inv.Category,
            ("name",),
            name="Swag Badge",
            description="We have a limited number of "
                        "<a href=\"/attend/shirts/\">Swag Badges</a> available "
                        f"for attendees of {settings.CONFERENCE_NAME}. "
                        "They will be allocated on a first come, first serve basis. "
                        "Please note that they are only available to Australian "
                        "attendees due to shipping limitations.",
            required=False,
            render_type=inv.Category.RENDER_TYPE_CHECKBOX,
            order=50,
        )
        self.extras = self.find_or_make(
            inv.Category,
            ("name",),
            name="Extras",
            description="Other items that can improve your conference "
                        "experience.",
            required=False,
            render_type=inv.Category.RENDER_TYPE_QUANTITY,
            order=60,
        )

        # Tickets

        self.ticket_contributor = self.find_or_make(
            inv.Product,
            ("name", "category",),
            category=self.ticket,
            name=settings.CONTRIBUTOR.name,
            price=settings.CONTRIBUTOR.regular_price,
            reservation_duration=hours(24),
            order=1,
        )
        self.ticket_professional = self.find_or_make(
            inv.Product,
            ("name", "category",),
            category=self.ticket,
            name=settings.PROFESSIONAL.name,
            price=settings.PROFESSIONAL.regular_price,
            reservation_duration=hours(24),
            order=10,
        )
        self.ticket_hobbyist = self.find_or_make(
            inv.Product,
            ("name", "category",),
            category=self.ticket,
            name=settings.HOBBYIST.name,
            price=settings.HOBBYIST.regular_price,
            reservation_duration=hours(24),
            order=20,
        )
        self.ticket_student = self.find_or_make(
            inv.Product,
            ("name", "category",),
            category=self.ticket,
            name=settings.STUDENT.name,
            price=settings.STUDENT.regular_price,
            reservation_duration=hours(24),
            order=30,
        )
        self.ticket_miniconf_only = self.find_or_make(
            inv.Product,
            ("name", "category",),
            category=self.ticket,
            name=settings.MINICONF_ONLY.name,
            price=settings.MINICONF_ONLY.regular_price,
            reservation_duration=hours(24),
            order=40,
        )
        self.ticket_speaker = self.find_or_make(
            inv.Product,
            ("name", "category",),
            category=self.ticket,
            name=settings.SPEAKER.name,
            price=settings.SPEAKER.regular_price,
            reservation_duration=hours(24),
            order=50,
        )
        self.ticket_media = self.find_or_make(
            inv.Product,
            ("name", "category",),
            category=self.ticket,
            name=settings.MEDIA.name,
            price=settings.MEDIA.regular_price,
            reservation_duration=hours(24),
            order=60,
        )
        self.ticket_sponsor = self.find_or_make(
            inv.Product,
            ("name", "category",),
            category=self.ticket,
            name=settings.SPONSOR.name,
            price=settings.SPONSOR.regular_price,
            reservation_duration=hours(24),
            order=70,
        )
        self.ticket_team = self.find_or_make(
            inv.Product,
            ("name", "category",),
            category=self.ticket,
            name=settings.CONFERENCE_ORG.name,
            price=settings.CONFERENCE_ORG.regular_price,
            reservation_duration=hours(24),
            order=80,
        )
        self.ticket_volunteer = self.find_or_make(
            inv.Product,
            ("name", "category",),
            category=self.ticket,
            name=settings.CONFERENCE_VOL.name,
            price=settings.CONFERENCE_VOL.regular_price,
            reservation_duration=hours(24),
            order=90,
        )

        # Agreements
        self.accept_terms = self.find_or_make(
            inv.Product,
            ("name", "category",),
            category=self.terms,
            name="I Accept",
            price=Decimal("00.00"),
            reservation_duration=hours(24),
            order=10,
            limit_per_user=1,
        )

        # for t in settings.PENGUIN_DINNER.tickets:
        #     self.find_or_make(
        #         inv.Product,
        #         ("name", "category",),
        #         category=self.penguin_dinner,
        #         name=t.name,
        #         description=t.description,
        #         price=t.price,
        #         reservation_duration=t.reservation,
        #         order=t.order()
        #     )

        # for t in settings.SPEAKERS_DINNER.tickets:
        #     self.find_or_make(
        #         inv.Product,
        #         ("name", "category",),
        #         category=self.speakers_dinner_ticket,
        #         name=t.name,
        #         description=t.description,
        #         price=t.price,
        #         reservation_duration=t.reservation,
        #         order=t.order()
        #     )

        # PDNS

        # self.pdns = self.find_or_make(
        #     inv.Product,
        #     ("name", "category",),
        #     category=self.pdns_category,
        #     name="Conference Attendee",
        #     price=Decimal("00.00"),
        #     reservation_duration=hours(1),
        #     limit_per_user=1,
        #     order=10,
        # )

        # # Accommodation

        # self.accommodation_week = self.find_or_make(
        #     inv.Product,
        #     ("name", "category",),
        #     category=self.accommodation,
        #     name="Single Bedroom with Shared Bathrooms, includes full "
        #          "breakfast, Sunday 15 January 2017--Saturday 21 January 2017",
        #     price=Decimal("396.00"),
        #     reservation_duration=hours(24),
        #     limit_per_user=1,
        #     order=10,
        # )

        # Extras

        self.swag_badge = self.find_or_make(
            inv.Product,
            ("name", "category",),
            category=self.badge_category,
            name="I would like a Swag Badge (if available)",
            price=Decimal("0.00"),
            reservation_duration=hours(24),
            limit_per_user=1,
            order=10,
        )

        self.carbon_offset = self.find_or_make(
            inv.Product,
            ("name", "category",),
            category=self.extras,
            name="Offset the carbon pollution generated by your attendance, "
                 "thanks to fifteen trees.",
            price=Decimal("5.00"),
            reservation_duration=hours(24),
            order=10,
        )


        # Shirts
        # ShirtGroup = namedtuple("ShirtGroup", ("prefix", "sizes"))
        # shirt_names = {
        #     "straight": ShirtGroup(
        #         "Straight Cut",
        #         ("S", "M", "L", "XL", "2XL", "3XL", "4XL", "5XL"),
        #     ),
        #     "semi_fitted": ShirtGroup(
        #         "Semi-Fitted",
        #         ("XS", "S", "M", "L", "XL", "2XL"),
        #     ),
        #     "fitted": ShirtGroup(
        #         "Fitted",
        #         ("XS", "S", "M", "L", "XL", "2XL"),
        #     ),
        # }

        # self.shirts = {}
        # order = 0
        # for name, group in shirt_names.items():
        #     self.shirts[name] = {}
        #     prefix = group.prefix
        #     for size in group.sizes:
        #         product_name = "%s %s" % (prefix, size)
        #         order += 10
        #         self.shirts[name][size] = self.find_or_make(
        #             inv.Product,
        #             ("name", "category",),
        #             name=product_name,
        #             category=self.t_shirt,
        #             price=settings.TSHIRT_PRICE,
        #             reservation_duration=hours(1),
        #             order=order,
        #         )

    def populate_restrictions(self):

        # Hide the products that will eventually need a voucher
        hide_voucher_products = self.find_or_make(
            cond.GroupMemberFlag,
            ("description", ),
            description="Can see hidden products",
            condition=cond.FlagBase.ENABLE_IF_TRUE,
        )
        hide_voucher_products.group.set([self.group_unpublish])
        hide_voucher_products.products.set([
            self.ticket_media,
            self.ticket_sponsor,
        ])

        hide_all_tickets = self.find_or_make(
            cond.GroupMemberFlag,
            ("description", ),
            description="Can pre-purchase tickets",
            condition=cond.FlagBase.ENABLE_IF_TRUE,
        )
        hide_all_tickets.group.set([self.group_prepurchase])
        hide_all_tickets.products.set([
            self.ticket_contributor,
            self.ticket_professional,
            self.ticket_hobbyist,
            self.ticket_student,
            self.ticket_miniconf_only,
        ])

        # Set limits.
        public_ticket_cap = self.find_or_make(
            cond.TimeOrStockLimitFlag,
            ("description", ),
            description="Public ticket cap",
            condition=cond.FlagBase.DISABLE_IF_FALSE,
            limit=600,
        )
        public_ticket_cap.products.set([
            self.ticket_contributor,
            self.ticket_professional,
            self.ticket_hobbyist,
            self.ticket_student,
        ])

        student_ticket_cap = self.find_or_make(
            cond.TimeOrStockLimitFlag,
            ("description", ),
            description="Student ticket cap",
            condition=cond.FlagBase.DISABLE_IF_FALSE,
            limit=100,
        )

        student_ticket_cap.products.set([
            self.ticket_student,
        ])

        public_ticket_cap.products.set([
            self.ticket_contributor,
            self.ticket_professional,
            self.ticket_hobbyist,
            self.ticket_student,
        ])

        sponsor_ticket_cap = self.find_or_make(
            cond.TimeOrStockLimitFlag,
            ("description", ),
            description="Reserved for sponsors",
            condition=cond.FlagBase.DISABLE_IF_FALSE,
            limit=70,
        )
        sponsor_ticket_cap.products.set([
            self.ticket_sponsor,
        ])

        volunteer_ticket_cap = self.find_or_make(
            cond.TimeOrStockLimitFlag,
            ("description", ),
            description="Reserved for volunteers and organisers",
            condition=cond.FlagBase.DISABLE_IF_FALSE,
            limit=62,
        )
        volunteer_ticket_cap.products.set([
            self.ticket_team,
            self.ticket_volunteer,
        ])

        media_ticket_cap = self.find_or_make(
            cond.TimeOrStockLimitFlag,
            ("description", ),
            description="Reserved for media",
            condition=cond.FlagBase.DISABLE_IF_FALSE,
            limit=10,
        )
        media_ticket_cap.products.set([
            self.ticket_media,
        ])

        speaker_ticket_cap = self.find_or_make(
            cond.TimeOrStockLimitFlag,
            ("description", ),
            description="Reserved for speakers (and miniconf organisers)",
            condition=cond.FlagBase.DISABLE_IF_FALSE,
            limit=104,
        )
        speaker_ticket_cap.products.set([
            self.ticket_speaker,
        ])

        # penguin_dinner_cap = self.find_or_make(
        #     cond.TimeOrStockLimitFlag,
        #     ("description", ),
        #     description="Penguin dinner ticket cap",
        #     condition=cond.FlagBase.DISABLE_IF_FALSE,
        #     limit=900,
        # )
        # penguin_dinner_cap.categories.set([
        #     self.penguin_dinner,
        # ])

        # speakers_dinner_cap = self.find_or_make(
        #     cond.TimeOrStockLimitFlag,
        #     ("description", ),
        #     description="Speakers dinner ticket cap",
        #     condition=cond.FlagBase.DISABLE_IF_FALSE,
        #     limit=135,
        # )
        # speakers_dinner_cap.categories.set([
        #     self.speakers_dinner_ticket,
        # ])

        # pdns_cap = self.find_or_make(
        #     cond.TimeOrStockLimitFlag,
        #     ("description", ),
        #     description="PDNS ticket cap",
        #     condition=cond.FlagBase.DISABLE_IF_FALSE,
        #     limit=400,
        # )
        # pdns_cap.categories.set([
        #     self.pdns_category,
        # ])

        # Volunteer tickets are for volunteers only
        volunteers = self.find_or_make(
            cond.GroupMemberFlag,
            ("description", ),
            description="Volunteer tickets",
            condition=cond.FlagBase.ENABLE_IF_TRUE,
        )
        volunteers.group.set([self.group_volunteers])
        volunteers.products.set([
            self.ticket_volunteer,
        ])

        # Team tickets are for team members only
        team = self.find_or_make(
            cond.GroupMemberFlag,
            ("description", ),
            description="Team tickets",
            condition=cond.FlagBase.ENABLE_IF_TRUE,
        )
        team.group.set([self.group_team])
        team.products.set([
            self.ticket_team,
        ])

        # Speaker tickets are for primary speakers only
        speaker_tickets = self.find_or_make(
            cond.SpeakerFlag,
            ("description", ),
            description="Speaker tickets",
            condition=cond.FlagBase.ENABLE_IF_TRUE,
            is_presenter=True,
            is_copresenter=False,
        )
        speaker_tickets.proposal_kind.set(self.main_conference_proposals)
        speaker_tickets.products.set([self.ticket_speaker, ])

        # Speaker dinner tickets are for primary speakers only
        # speaker_dinner_tickets = self.find_or_make(
        #     cond.SpeakerFlag,
        #     ("description", ),
        #     description="Speaker dinner tickets",
        #     condition=cond.FlagBase.ENABLE_IF_TRUE,
        #     is_presenter=True,
        #     is_copresenter=False,
        # )
        # speaker_dinner_tickets.proposal_kind.set(self.main_conference_proposals)
        # speaker_dinner_tickets.categories.set([self.speakers_dinner_ticket, ])

        # PDNS tickets are complicated.
        # They can be enabled by tickets
        # pdns_by_ticket = self.find_or_make(
        #     cond.ProductFlag,
        #     ("description", ),
        #     description="PDNS available by ticket",
        #     condition=cond.FlagBase.ENABLE_IF_TRUE,
        # )
        # pdns_by_ticket.enabling_products.set([
        #     self.ticket_professional,
        #     self.ticket_contributor,
        #     self.ticket_media,
        #     self.ticket_sponsor,
        # ])
        # pdns_by_ticket.categories.set([self.pdns_category, ])

        # They are available to speakers
        # pdns_by_speaker = self.find_or_make(
        #     cond.SpeakerFlag,
        #     ("description", ),
        #     description="PDNS available to speakers",
        #     condition=cond.FlagBase.ENABLE_IF_TRUE,
        #     is_presenter=True,
        #     is_copresenter=True,

        # )
        # pdns_by_speaker.proposal_kind.set(self.main_conference_proposals)
        # pdns_by_speaker.categories.set([self.pdns_category, ])

        # They are available to staff
        # pdns_by_staff = self.find_or_make(
        #     cond.GroupMemberFlag,
        #     ("description", ),
        #     description="PDNS available to staff",
        #     condition=cond.FlagBase.ENABLE_IF_TRUE,
        # )
        # pdns_by_staff.group.set([
        #     self.group_team,
        # ])
        # pdns_by_staff.categories.set([self.pdns_category, ])

        # Don't allow people to get anything if they don't have a ticket first
        needs_a_ticket = self.find_or_make(
            cond.CategoryFlag,
            ("description", ),
            description="GottaGettaTicketFirst",
            condition=cond.FlagBase.DISABLE_IF_FALSE,
            enabling_category=self.ticket
        )
        needs_a_ticket.categories.set([
            self.extras,
            # self.t_shirt,
            # self.penguin_dinner,
            # self.pdns_category,
        ])
        # Require attendees to accept the T&Cs and Code of Conduct
        needs_agreement = self.find_or_make(
            cond.CategoryFlag,
            ("description", ),
            description="Must Accept Terms",
            condition=cond.FlagBase.DISABLE_IF_FALSE,
            enabling_category=self.terms,
        )
        needs_agreement.categories.set([
            self.extras,
            # self.t_shirt,
            # self.penguin_dinner,
            # self.pdns_category,
            # self.speakers_dinner_ticket,
        ])

    def populate_discounts(self):
        def add_early_birds(discount):
            self.find_or_make(
                cond.DiscountForProduct,
                ("discount", "product"),
                discount=discount,
                product=self.ticket_contributor,
                price=settings.CONTRIBUTOR.earlybird_discount(),
                quantity=1,  # Per user
            )
            self.find_or_make(
                cond.DiscountForProduct,
                ("discount", "product"),
                discount=discount,
                product=self.ticket_professional,
                price=settings.PROFESSIONAL.earlybird_discount(),
                quantity=1,  # Per user
            )

        def free_category(parent_discount, category, quantity=1):
            self.find_or_make(
                cond.DiscountForCategory,
                ("discount", "category",),
                discount=parent_discount,
                category=category,
                percentage=Decimal("100.00"),
                quantity=quantity,
            )

        # Early Bird Discount (general public)
        # early_bird_hobbyist_discount = self.find_or_make(
        #     cond.TimeOrStockLimitDiscount,
        #     ("description", ),
        #     description="Early Bird Discount - Hobbyist",
        #     end_time=settings.EARLY_BIRD_DEADLINE,
        #     limit=150,  # Across all users
        # )
        # self.find_or_make(
        #         cond.DiscountForProduct,
        #         ("discount", "product"),
        #         discount=early_bird_hobbyist_discount,
        #         product=self.ticket_hobbyist,
        #         price=settings.HOBBYIST.earlybird_discount(),
        #         quantity=1,  # Per user
        # )

        # early_bird = self.find_or_make(
        #     cond.TimeOrStockLimitDiscount,
        #     ("description", ),
        #     description="Early Bird Discount - Professional",
        #     end_time=settings.EARLY_BIRD_DEADLINE,
        #     limit=200,  # Across professionals and fairy sponsors
        # )
        # add_early_birds(early_bird)

        # Early bird rates for speakers
        speaker_ticket_discounts = self.find_or_make(
            cond.SpeakerDiscount,
            ("description", ),
            description="Speaker Ticket Discount",
            is_presenter=True,
            is_copresenter=True,
        )
        speaker_ticket_discounts.proposal_kind.set(
            self.main_conference_proposals,
        )
        add_early_birds(speaker_ticket_discounts)

        # Primary speaker gets a free speaker dinner ticket
        primary_speaker = self.find_or_make(
            cond.SpeakerDiscount,
            ("description", ),
            description="Complimentary for primary proposer",
            is_presenter=True,
            is_copresenter=False,
        )
        primary_speaker.proposal_kind.set(self.main_conference_proposals)
        # free_category(primary_speaker, self.speakers_dinner_ticket)

        # Professional-Like ticket inclusions
        ticket_prolike_inclusions = self.find_or_make(
            cond.IncludedProductDiscount,
            ("description", ),
            description="Complimentary for ticket holder (Professional-level)",
        )
        ticket_prolike_inclusions.enabling_products.set([
            self.ticket_contributor,
            self.ticket_professional,
            self.ticket_media,
            self.ticket_sponsor,
            self.ticket_speaker,
        ])
        # free_category(ticket_prolike_inclusions, self.penguin_dinner)
        # free_category(ticket_prolike_inclusions, self.t_shirt)

        # Hobbyist ticket inclusions
        ticket_hobbyist_inclusions = self.find_or_make(
            cond.IncludedProductDiscount,
            ("description", ),
            description="Complimentary for ticket holder (Hobbyist-level)",
        )
        ticket_hobbyist_inclusions.enabling_products.set([
            self.ticket_hobbyist,
        ])
        # free_category(ticket_hobbyist_inclusions, self.t_shirt)

        # Student ticket inclusions
        ticket_student_inclusions = self.find_or_make(
            cond.IncludedProductDiscount,
            ("description", ),
            description="Complimentary for ticket holder (Student-level)",
        )
        ticket_student_inclusions.enabling_products.set([
            self.ticket_student,
        ])
        # free_category(ticket_student_inclusions, self.t_shirt)

        # Team ticket inclusions
        ticket_staff_inclusions = self.find_or_make(
            cond.IncludedProductDiscount,
            ("description", ),
            description="Complimentary for ticket holder (Staff)",
        )
        ticket_staff_inclusions.enabling_products.set([
            self.ticket_team,
        ])
        # free_category(ticket_staff_inclusions, self.penguin_dinner)

        # Team & volunteer shirts, regardless of ticket type
        # staff_t_shirts = self.find_or_make(
        #     cond.GroupMemberDiscount,
        #     ("description", ),
        #     description="Shirts complimentary for staff and volunteers",
        # )
        # staff_t_shirts.group.set([
        #     self.group_team,
        #     self.group_volunteers,
        # ])
        # free_category(staff_t_shirts, self.t_shirt, quantity=5)

        print(f"{self.count} categories found/made")

    def find_or_make(self, model, search_keys, **k):
        ''' Either makes or finds an object of type _model_, with the given
        kwargs.

        Arguments:
            search_keys ([str, ...]): A sequence of keys that are used to search
            for an existing version in the database. The remaining arguments are
            only used when creating a new object.
        '''
        self.count += 1
        try:
            keys = dict((key, k[key]) for key in search_keys)
            a = model.objects.get(**keys)
            self.stdout.write("FOUND  : " + str(keys))
            model.objects.filter(id=a.id).update(**k)
            a.refresh_from_db()
            return a
        except ObjectDoesNotExist:
            a = model.objects.create(**k)
            self.stdout.write("CREATED: " + str(k))
            return a


def hours(n):
    return timedelta(hours=n)