from datetime import datetime, timedelta, date

from django.test import TestCase
from django.utils import timezone

from coin.members.models import Member
from .models import Item, ItemType, Loan


def localize(naive_dt):
    if not timezone.is_naive(naive_dt):
        raise ValueError('Expecting a naive datetime')
    else:
        return timezone.make_aware(naive_dt, timezone.get_current_timezone())


class HardwareModelsFactoryMixin:
    def get_item_type(self, **kwargs):
        params = {'name': 'Foos'}
        params.update(**kwargs)
        item_type, _ = ItemType.objects.get_or_create(**kwargs)
        return item_type

    def get_item(self, **kwargs):
        params = {
            'type': self.get_item_type(),
            'designation': 'Test item',
        }
        params.update(**kwargs)
        item, _ = Item.objects.get_or_create(**params)
        return item


class HardwareLoaningTestCase(HardwareModelsFactoryMixin, TestCase):
    def setUp(self):
        self.member = Member.objects.create(username='jdoe')
        self.item = self.get_item()

    def test_running_(self):
        loan_start_date = localize(datetime(2011, 1, 14, 12, 0, 0))
        loan = Loan.objects.create(
            item=self.item, user=self.member,
            loan_date=loan_start_date)

        self.assertEqual(Loan.objects.running().count(), 1)
        self.assertEqual(Loan.objects.finished().count(), 0)
        loan.item.give_back()
        self.assertEqual(Loan.objects.running().count(), 0)
        self.assertEqual(Loan.objects.finished().count(), 1)


class ItemTestCase(HardwareModelsFactoryMixin, TestCase):
    def setUp(self):
        self.member = Member.objects.create(username='jdoe')

        self.free_item = self.get_item(designation='free')
        self.deployed_item = self.get_item(
            designation='deployed', deployed=True)
        self.borrowed_item = self.get_item(designation='borrowed')

    def test_queryset_methods(self):
        self.assertEqual(Item.objects.borrowed().count(), 0)
        self.assertEqual(Item.objects.deployed().count(), 1)
        self.assertEqual(Item.objects.available().count(), 2)
        self.assertEqual(Item.objects.unavailable().count(), 1)

        Loan.objects.create(
            item=self.borrowed_item, user=self.member,
            loan_date=localize(datetime(2011, 1, 14, 12, 0, 0)))

        self.assertEqual(Item.objects.borrowed().count(), 1)
        self.assertEqual(Item.objects.deployed().count(), 1)
        self.assertEqual(Item.objects.available().count(), 1)
        self.assertEqual(Item.objects.unavailable().count(), 2)