# -*- coding: utf-8 -*-
"""Test suite for django-unfriendly."""

import datetime

from django.http import HttpResponseNotFound
from django.core.urlresolvers import reverse
from django.template.defaultfilters import slugify
from django.test import TestCase
from mock import patch

from unfriendly import settings
from unfriendly.utils import CheckSumError, encrypt, decrypt
from unfriendly.templatetags.unfriendly_tags import obfuscate


class UnfriendlyTests(TestCase):
    """Test case for django-unfriendly."""
    urls = 'unfriendly.tests.urls'

    def setUp(self):
        self.juice = 'Lorem ipsum dolor sit amet'

    def test_encryption(self):
        """
        Test the encryption.
        """
        original = self.juice

        obfuscated = encrypt(original, settings.UNFRIENDLY_SECRET,
                             settings.UNFRIENDLY_IV)
        self.assertNotEqual(original, obfuscated)

        deobfuscated = decrypt(obfuscated, settings.UNFRIENDLY_SECRET,
                               settings.UNFRIENDLY_IV)
        self.assertEqual(original, deobfuscated)

    def test_encryption_oddkey(self):
        """
        Test the encryption with an odd length secret key.
        """
        original = self.juice

        obfuscated = encrypt(original, settings.UNFRIENDLY_SECRET[0:11],
                             settings.UNFRIENDLY_IV)
        self.assertNotEqual(original, obfuscated)

        deobfuscated = decrypt(obfuscated, settings.UNFRIENDLY_SECRET[0:11],
                               settings.UNFRIENDLY_IV)
        self.assertEqual(original, deobfuscated)

    def test_encryption_checksum(self):
        """
        Test the encryption with bad checksums.
        """
        original = self.juice

        obfuscated = encrypt(original, settings.UNFRIENDLY_SECRET,
                             settings.UNFRIENDLY_IV)

        # Add characters to the end (cannot unpack checksum)
        self.assertRaises(
            CheckSumError,
            decrypt, obfuscated + 'oops', settings.UNFRIENDLY_SECRET,
            settings.UNFRIENDLY_IV)

        # Replace last few characters (checksum mismatch)
        self.assertRaises(
            CheckSumError,
            decrypt, obfuscated[-4:] + 'oops', settings.UNFRIENDLY_SECRET,
            settings.UNFRIENDLY_IV)

    def test_obfuscate_filter(self):
        """
        Test the obfuscate filter.
        """
        test_url = reverse('unfriendly-test')
        obfuscated_url = obfuscate(test_url)
        view_url = reverse('unfriendly-deobfuscate', kwargs={
            'key': encrypt(test_url, settings.UNFRIENDLY_SECRET,
                           settings.UNFRIENDLY_IV),
        })
        self.assertEqual(view_url, obfuscated_url)

    def test_obfuscate_filter_with_juice(self):
        """
        Test the obfuscate filter.
        """
        test_url = reverse('unfriendly-test')
        obfuscated_url = obfuscate(test_url, self.juice)
        view_url = reverse('unfriendly-deobfuscate', kwargs={
            'juice': slugify(self.juice),
            'key': encrypt(test_url, settings.UNFRIENDLY_SECRET,
                           settings.UNFRIENDLY_IV),
        })
        self.assertEqual(view_url, obfuscated_url)

    @patch('unfriendly.templatetags.unfriendly_tags.settings.UNFRIENDLY_ENABLE_FILTER',
           False)
    def test_obfuscate_filter_disabled(self):
        """
        Test the obfuscate filter when disabled in settings.
        """
        test_url = reverse('unfriendly-test')
        obfuscated_url = obfuscate(test_url)
        view_url = reverse('unfriendly-deobfuscate', kwargs={
            'key': encrypt(test_url, settings.UNFRIENDLY_SECRET,
                           settings.UNFRIENDLY_IV),
        })
        self.assertNotEqual(view_url, obfuscated_url)
        self.assertNotEqual(view_url, test_url)

    @patch('unfriendly.templatetags.unfriendly_tags.settings.UNFRIENDLY_ENABLE_FILTER',
           False)
    def test_obfuscate_filter_with_juice_disabled(self):
        """
        Test the obfuscate filter when disabled in settings.
        """
        test_url = reverse('unfriendly-test')
        obfuscated_url = obfuscate(test_url, self.juice)
        view_url = reverse('unfriendly-deobfuscate', kwargs={
            'juice': slugify(self.juice),
            'key': encrypt(test_url, settings.UNFRIENDLY_SECRET,
                           settings.UNFRIENDLY_IV),
        })
        self.assertNotEqual(view_url, obfuscated_url)
        self.assertNotEqual(view_url, test_url)

    def test_deobfuscate_view(self):
        """
        Test the deobfuscate view.
        """
        test_url = reverse('unfriendly-test')
        obfuscated_url = obfuscate(test_url)

        test_response = self.client.get(test_url)
        obfuscated_response = self.client.get(obfuscated_url)

        self.assertEqual(test_response.content, obfuscated_response.content)

    def test_deobfuscate_view_with_juice(self):
        """
        Test the deobfuscate view with seo juice.
        """
        test_url = reverse('unfriendly-test')
        obfuscated_url = obfuscate(test_url, self.juice)

        test_response = self.client.get(test_url)
        obfuscated_response = self.client.get(obfuscated_url)

        self.assertEqual(test_response.content, obfuscated_response.content)

    def test_deobfuscate_view_bad_path(self):
        """
        Test the deobfuscate view with a bad url path.
        """
        test_url = 'bad-path'
        obfuscated_url = obfuscate(test_url)
        response = self.client.get(obfuscated_url)
        self.assertEqual(response.status_code, 404)

    def test_deobfuscate_view_404(self):
        """
        Test deobfuscate view with hacked url.
        """
        view_url = reverse('unfriendly-deobfuscate', kwargs={
            'key': 'hacked-key',
        })
        response = self.client.get(view_url)
        self.assertEqual(response.status_code, 404)

    def test_deobfuscate_view_404_invalid_key(self):
        """
        Test deobfuscate view with an invalid key (too short).
        """
        view_url = reverse('unfriendly-deobfuscate', kwargs={
            'key': 'i',
        })
        response = self.client.get(view_url)
        self.assertEqual(response.status_code, 404)
