from datetime import datetime

from django.contrib.auth.models import User
from django.test import TestCase

from coupons.forms import CouponForm
from coupons.models import Coupon


class DefaultCouponTestCase(TestCase):
    def setUp(self):
        self.user = User.objects.create(username="user1")
        self.coupon = Coupon.objects.create_coupon('monetary', 100)

    def test_redeem(self):
        self.coupon.redeem(self.user)
        self.assertTrue(self.coupon.is_redeemed)
        self.assertEquals(self.coupon.users.count(), 1)
        self.assertIsInstance(self.coupon.users.first().redeemed_at, datetime)
        self.assertEquals(self.coupon.users.first().user, self.user)

    def test_redeem_via_form(self):
        form = CouponForm(data={'code': self.coupon.code}, user=self.user)
        # form should be valid
        self.assertTrue(form.is_valid())
        # perform redeem
        self.coupon.redeem(self.user)
        # coupon should be redeemed properly now
        self.assertTrue(self.coupon.is_redeemed)
        self.assertEquals(self.coupon.users.count(), 1)
        self.assertIsInstance(self.coupon.users.first().redeemed_at, datetime)
        self.assertEquals(self.coupon.users.first().user, self.user)
        # form should be invalid after redeem
        self.assertTrue(form.is_valid())

    def test_redeem_via_form_without_user(self):
        form = CouponForm(data={'code': self.coupon.code})
        # form should be valid
        self.assertTrue(form.is_valid())
        # perform redeem
        self.coupon.redeem()
        # coupon should be redeemed properly now
        self.assertTrue(self.coupon.is_redeemed)
        self.assertEquals(self.coupon.users.count(), 1)
        self.assertIsInstance(self.coupon.users.first().redeemed_at, datetime)
        self.assertIsNone(self.coupon.users.first().user)
        # form should be invalid after redeem
        self.assertTrue(form.is_valid())


class SingleUserCouponTestCase(TestCase):
    def setUp(self):
        self.user = User.objects.create(username="user1")
        self.coupon = Coupon.objects.create_coupon('monetary', 100, self.user)

    def test_user_limited_coupon(self):
        self.assertEquals(self.coupon.users.count(), 1)
        self.assertEquals(self.coupon.users.first().user, self.user)
        # not redeemed yet
        self.assertIsNone(self.coupon.users.first().redeemed_at)

    def test_redeem_with_user(self):
        self.coupon.redeem(self.user)
        # coupon should be redeemed properly now
        self.assertTrue(self.coupon.is_redeemed)
        self.assertEquals(self.coupon.users.count(), 1)
        self.assertIsInstance(self.coupon.users.first().redeemed_at, datetime)
        self.assertEquals(self.coupon.users.first().user, self.user)

    def test_form_without_user(self):
        """ This should fail since the coupon is bound to an user, but we do not provide any user. """
        form = CouponForm(data={'code': self.coupon.code})
        self.assertFalse(form.is_valid())
        self.assertEquals(
            form.errors,
            {'code': ['This code is not valid for your account.']}
        )

    def test_redeem_with_user_twice(self):
        self.test_redeem_with_user()
        # try to redeem again with form
        form = CouponForm(data={'code': self.coupon.code}, user=self.user)
        self.assertFalse(form.is_valid())
        self.assertEquals(
            form.errors,
            {'code': ['This code has already been used.']}
        )

@@ -3486,20 +3486,1387 @@
  used.'%5D%7D%0A        )%0A
+%0A%0Aclass UnlimitedCouponTestCase(TestCase):%0A    def setUp(self):%0A        self.user = User.objects.create(username=%22user1%22)%0A        self.coupon = Coupon.objects.create_coupon('monetary', 100, user_limit=0)%0A%0A    def test_redeem_with_user(self):%0A        self.coupon.redeem(self.user)%0A        # coupon should be redeemed properly now%0A        self.assertTrue(self.coupon.is_redeemed)%0A        self.assertEquals(self.coupon.users.count(), 1)%0A        self.assertIsInstance(self.coupon.users.first().redeemed_at, datetime)%0A        self.assertEquals(self.coupon.users.first().user, self.user)%0A%0A    def test_form_without_user(self):%0A        %22%22%22 This should fail since we cannot track single use of a coupon without an user. %22%22%22%0A        form = CouponForm(data=%7B'code': self.coupon.code%7D)%0A        self.assertFalse(form.is_valid())%0A        self.assertEquals(%0A            form.errors,%0A            %7B'code': %5B'The server must provide an user to this form to allow you to use this code. Maybe you need to sign in?'%5D%7D%0A        )%0A%0A    def test_redeem_with_user_twice(self):%0A        self.test_redeem_with_user()%0A        # try to redeem again with form%0A        form = CouponForm(data=%7B'code': self.coupon.code%7D, user=self.user)%0A        self.assertFalse(form.is_valid())%0A        self.assertEquals(%0A            form.errors,%0A            %7B'code': %5B'This code has already been used.'%5D%7D%0A        )%0A

add test cases for multi user coupons