import os

from django.test import TestCase
from django.test.utils import override_settings

from django.conf import settings
from django.contrib.auth import authenticate
from django.contrib.auth.models import User, Group

from userprofile.forms import USERNAME_MIN_LENGTH

from userprofile.models import Producer, UserImage

TEST_ROOT = settings.MEDIA_ROOT + '/private/unittest'

TESTPRODUCER = 'unittest_prod'
TESTUSER = 'unittest_user'
TESTPASSWORD = 'testpassword'
TESTEMAIL = 'test@example.com'
TESTPAYPAL = 'paypal@example.com'

PRODUCER_URLS = [
	'/profile/registration/pictureupload',
	'/profile/registration/pictures',
	'/profile/registration/info',
	'/profile/payment',
	'/profile/pictureupload',
	'/profile/pictures',
	'/profile/info',
]

USER_URLS = [
	'/profile/changepassword',
]

@override_settings(PREPEND_WWW=False)
class LoggedOutTest(TestCase):
	def setUp(self):
		os.environ['RECAPTCHA_TESTING'] = 'True'
		settings.OPEN = True

	def tearDown(self):
		os.environ['RECAPTCHA_TESTING'] = 'False'

	def test_home(self):
		r = self.client.get('/')
		self.assertEqual(r.status_code, 200)

	def test_urls(self):
		for url in PRODUCER_URLS + USER_URLS:
			r = self.client.get(url)
			self.assertEqual(r.status_code, 302)

	def test_login_redirect(self):
		url = USER_URLS[0]
		r = self.client.get(url)
		self.assertRedirects(r, '/accounts/login/?next=/profile/changepassword')

	def test_register_user(self):
		r = self.client.post('/register_user', {
			'username': TESTUSER,
			'password1': TESTPASSWORD,
			'password2': TESTPASSWORD,
			'email': TESTEMAIL,
			'recaptcha_response_field': 'PASSED',
		})

		# Check for redirect upon successful registration
		self.assertRedirects(r, '/video/list')

		u = User.objects.get(username=TESTUSER)
		self.assertEqual(u.username, TESTUSER)
		self.assertEqual(u.email, TESTEMAIL)

		# Check that no producer entry was made for the user
		self.assertEqual(0, Producer.objects.filter(user=u).count())

	def test_register_producer(self):
		r = self.client.post('/register_producer', {
			'username': TESTPRODUCER,
			'password1': TESTPASSWORD,
			'password2': TESTPASSWORD,
			'email': TESTEMAIL,
			'recaptcha_response_field': 'PASSED',
		})

		# Check for redirect upon successful registration
		self.assertRedirects(r, '/profile/registration/pictureupload')

		u = User.objects.get(username=TESTPRODUCER)
		self.assertEqual(u.username, TESTPRODUCER)
		self.assertEqual(u.email, TESTEMAIL)

		p = u.producer
		self.assertTrue(p)
		self.assertFalse(p.approved)

	def test_bad_registration(self):
		r = self.client.post('/register_user', {
			'username': TESTUSER,
			'password1': TESTPASSWORD,
			'password2': 'wrong!!!',
			'email': TESTEMAIL,
			'recaptcha_response_field': 'PASSED',
		})

		self.assertFormError(r, 'form', None, 'The two passwords you entered didn\'t match.')

		r = self.client.post('/register_user', {
			'username': TESTUSER,
			'password1': 'wrong!!!',
			'password2': TESTPASSWORD,
			'email': TESTEMAIL,
			'recaptcha_response_field': 'PASSED',
		})

		self.assertFormError(r, 'form', None, 'The two passwords you entered didn\'t match.')

	def test_valid_username(self):
		r = self.client.post('/register_user', {
			'username': 'aa',
			'password1': TESTPASSWORD,
			'password2': TESTPASSWORD,
			'email': TESTEMAIL,
			'recaptcha_response_field': 'PASSED',
		})

		self.assertFormError(r, 'form', 'username', 'Ensure this value has at least 3 characters (it has 2).')

		r = self.client.post('/register_user', {
			'username': ' a  ',
			'password1': TESTPASSWORD,
			'password2': TESTPASSWORD,
			'email': TESTEMAIL,
			'recaptcha_response_field': 'PASSED',
		})

		self.assertFormError(r, 'form', 'username', "Your username must be at least %d characters long." % USERNAME_MIN_LENGTH)

		r = self.client.post('/register_user', {
			'username': '8whatever',
			'password1': TESTPASSWORD,
			'password2': TESTPASSWORD,
			'email': TESTEMAIL,
			'recaptcha_response_field': 'PASSED',
		})

		self.assertFormError(r, 'form', 'username', "Your username must begin with a letter a-z.")


@override_settings(PREPEND_WWW=False)
class UserTest(TestCase):
	def setUp(self):
		self.user = User.objects.create_user(TESTUSER, TESTEMAIL, TESTPASSWORD)

	def test_urls(self):
		for url in PRODUCER_URLS:
			r = self.client.get(url)
			self.assertEqual(r.status_code, 302)

	def test_login_redirect(self):
		url = PRODUCER_URLS[0]
		r = self.client.get(url)
		self.assertRedirects(r, '/accounts/login/?next=/profile/registration/pictureupload')


@override_settings(PREPEND_WWW=False)
class ProducerTest(TestCase):
	def setUp(self):
		os.environ['RECAPTCHA_TESTING'] = 'True'

		# This registers a new producer
		r = self.client.post('/register_producer', {
			'username': TESTPRODUCER,
			'password1': TESTPASSWORD,
			'password2': TESTPASSWORD,
			'email': TESTEMAIL,
			'recaptcha_response_field': 'PASSED',
		})

		self.assertTrue(self.client.login(username=TESTPRODUCER, password=TESTPASSWORD))

	def tearDown(self):
		os.environ['RECAPTCHA_TESTING'] = 'False'

		# Delete all image files
		images = UserImage.objects.all()
		for i in images:
			i.image.delete()
			i.thumbnail.delete()

	def get_user(self):
		return User.objects.get(username=TESTPRODUCER)

	def test_urls(self):
		for url in PRODUCER_URLS:
			r = self.client.get(url)
			self.assertEqual(r.status_code, 200)

		r = self.client.get('/u/' + TESTPRODUCER)
		self.assertEqual(r.status_code, 200)

	def test_payment(self):
		url = '/profile/ajax/payment'
		p = self.get_user().producer

		# First the producer is not approved, so this shouldn't work
		self.client.post(url, {
			'paypal': TESTPAYPAL,
		})

		# Need to re-load the producer object
		p = Producer.objects.get(id=p.id)

		self.assertEqual(p.paypal, '')

		# Now approve them, and it should save
		p.approved = True
		p.save()

		self.client.post(url, {
			'paypal': TESTPAYPAL,
		})

		# Need to re-load the producer object
		p = Producer.objects.get(id=p.id)

		self.assertEqual(p.paypal, TESTPAYPAL)

		p.approved = False
		p.save()

	def test_picture_upload(self):
		imagepath = os.path.join(TEST_ROOT, 'test.jpg')

		# We'll try uploading two pictures, and then delete one of them.
		for i in range(2):
			with open(imagepath) as fp:
				self.client.post('/profile/pictureupload', {
					'form-0-image': fp,
					'form-TOTAL_FORMS': 1,
					'form-INITIAL_FORMS': 0,
					'form-MAX_NUM_FORMS': 1000,
				})

		# Make sure the pictures uploaded successfully
		images = self.get_user().userimage_set.all()
		self.assertEqual(len(images), 2)

		# Test that the files exist
		for i in range(2):
			userimage = images[i]
			pathname = os.path.join(settings.MEDIA_ROOT, 'p', 'uploads', 'userimages', 'full', os.path.basename(userimage.image.url))
			self.assertTrue(os.path.exists(pathname))

			if i == 0:
				path_delete = pathname
			else:
				path_profile = pathname

		# Now try to delete one
		self.client.post('/profile/ajax/pictures', {
			'delete': (images[0].id, )
		})

		# Make sure one picture was deleted
		images = self.get_user().userimage_set.all()
		self.assertEqual(len(images), 1)

		self.assertFalse(os.path.exists(path_delete))
		self.assertTrue(os.path.exists(path_profile))

		# Delete the remaining picture manually
		images[0].image.delete()
		images[0].delete()

		self.assertFalse(os.path.exists(path_profile))

	def test_bad_picture_upload(self):
		imagepath = os.path.join(TEST_ROOT, 'test.jp;g')

		with open(imagepath) as fp:
			self.client.post('/profile/pictureupload', {
				'form-0-image': fp,
				'form-TOTAL_FORMS': 1,
				'form-INITIAL_FORMS': 0,
				'form-MAX_NUM_FORMS': 1000,
			})

		# No images should have gotten uploaded
		self.assertEqual(self.get_user().userimage_set.all().count(), 0)


