import re

import mock
from nose.tools import eq_
from pyquery import PyQuery as pq

from django.core.files import temp

import amo
import amo.tests
from amo.urlresolvers import reverse
from amo.tests import formset, initial
from addons.models import Addon, AddonUser
from applications.models import AppVersion
from devhub.models import ActivityLog
from files.models import File
from users.models import UserProfile
from versions.models import ApplicationsVersions, Version


class TestVersion(amo.tests.TestCase):
    fixtures = ['base/users', 'base/addon_3615']

    def setUp(self):
        super(TestVersion, self).setUp()
        self.client.login(username='del@icio.us', password='password')
        self.user = UserProfile.objects.get(email='del@icio.us')
        self.addon = self.get_addon()
        self.version = Version.objects.get(id=81551)
        self.url = self.addon.get_dev_url('versions')

        self.disable_url = self.addon.get_dev_url('disable')
        self.enable_url = self.addon.get_dev_url('enable')
        self.unlist_url = self.addon.get_dev_url('unlist')
        self.delete_url = reverse('devhub.versions.delete', args=['a3615'])
        self.delete_data = {'addon_id': self.addon.pk,
                            'version_id': self.version.pk}

    def get_addon(self):
        return Addon.objects.get(id=3615)

    def get_doc(self):
        res = self.client.get(self.url)
        eq_(res.status_code, 200)
        return pq(res.content)

    def test_version_status_public(self):
        doc = self.get_doc()
        assert doc('.addon-status')

        self.addon.update(status=amo.STATUS_DISABLED, disabled_by_user=True)
        doc = self.get_doc()
        assert doc('.addon-status .status-admin-disabled')
        eq_(doc('.addon-status .status-admin-disabled').text(),
            'Disabled by Mozilla')

        self.addon.update(disabled_by_user=False)
        doc = self.get_doc()
        eq_(doc('.addon-status .status-admin-disabled').text(),
            'Disabled by Mozilla')

        self.addon.update(status=amo.STATUS_PUBLIC, disabled_by_user=True)
        doc = self.get_doc()
        eq_(doc('.addon-status .status-disabled').text(),
            'You have disabled this add-on')

    def test_no_validation_results(self):
        doc = self.get_doc()
        v = doc('td.file-validation').text()
        eq_(re.sub(r'\s+', ' ', v),
            'All Platforms Not validated. Validate now.')
        eq_(doc('td.file-validation a').attr('href'),
            reverse('devhub.file_validation',
                    args=[self.addon.slug, self.version.all_files[0].id]))

    def test_upload_link_label_in_edit_nav(self):
        url = reverse('devhub.versions.edit',
                      args=(self.addon.slug, self.version.pk))
        r = self.client.get(url)
        doc = pq(r.content)
        eq_(doc('.addon-status>.addon-upload>strong>a').text(),
            'Upload a new file')

    def test_delete_message(self):
        """Make sure we warn our users of the pain they will feel."""
        r = self.client.get(self.url)
        doc = pq(r.content)
        eq_(doc('#modal-delete p').eq(0).text(),
            'Deleting your add-on will permanently remove it from the site '
            'and prevent its GUID from being submitted ever again, even by '
            'you. The existing users of your add-on will remain on this '
            'update channel and never receive updates again.')

    def test_delete_message_if_bits_are_messy(self):
        """Make sure we warn krupas of the pain they will feel."""
        self.addon.highest_status = amo.STATUS_NULL
        self.addon.status = amo.STATUS_UNREVIEWED
        self.addon.save()

        r = self.client.get(self.url)
        doc = pq(r.content)
        eq_(doc('#modal-delete p').eq(0).text(),
            'Deleting your add-on will permanently remove it from the site '
            'and prevent its GUID from being submitted ever again, even by '
            'you. The existing users of your add-on will remain on this '
            'update channel and never receive updates again.')

    def test_delete_message_incomplete(self):
        """
        If an addon has highest_status = 0, they shouldn't be bothered with a
        blacklisting threat if they hit delete.
        """
        self.addon.highest_status = amo.STATUS_NULL
        self.addon.status = amo.STATUS_NULL
        self.addon.save()
        r = self.client.get(self.url)
        doc = pq(r.content)
        # Normally 2 paragraphs, one is the warning which we should take out.
        eq_(doc('#modal-delete p.warning').length, 0)

    def test_delete_version(self):
        self.client.post(self.delete_url, self.delete_data)
        assert not Version.objects.filter(pk=81551).exists()
        eq_(ActivityLog.objects.filter(action=amo.LOG.DELETE_VERSION.id)
            .count(), 1)

    def test_delete_version_then_detail(self):
        version, file = self._extra_version_and_file(amo.STATUS_LITE)
        self.client.post(self.delete_url, self.delete_data)
        res = self.client.get(reverse('addons.detail', args=[self.addon.slug]))
        eq_(res.status_code, 200)

    def test_cant_delete_version(self):
        self.client.logout()
        res = self.client.post(self.delete_url, self.delete_data)
        eq_(res.status_code, 302)
        assert Version.objects.filter(pk=81551).exists()

    def test_version_delete_status_null(self):
        res = self.client.post(self.delete_url, self.delete_data)
        eq_(res.status_code, 302)
        eq_(self.addon.versions.count(), 0)
        eq_(Addon.objects.get(id=3615).status, amo.STATUS_NULL)

    def _extra_version_and_file(self, status):
        version = Version.objects.get(id=81551)

        version_two = Version(addon=self.addon,
                              license=version.license,
                              version='1.2.3')
        version_two.save()

        file_two = File(status=status, version=version_two)
        file_two.save()
        return version_two, file_two

    def test_version_delete_status(self):
        self._extra_version_and_file(amo.STATUS_PUBLIC)

        res = self.client.post(self.delete_url, self.delete_data)
        eq_(res.status_code, 302)
        eq_(self.addon.versions.count(), 1)
        eq_(Addon.objects.get(id=3615).status, amo.STATUS_PUBLIC)

    def test_version_delete_status_unreviewd(self):
        self._extra_version_and_file(amo.STATUS_BETA)

        res = self.client.post(self.delete_url, self.delete_data)
        eq_(res.status_code, 302)
        eq_(self.addon.versions.count(), 1)
        eq_(Addon.objects.get(id=3615).status, amo.STATUS_UNREVIEWED)

    @mock.patch('files.models.File.hide_disabled_file')
    def test_user_can_disable_addon(self, hide_mock):
        self.addon.update(status=amo.STATUS_PUBLIC,
                          disabled_by_user=False)
        res = self.client.post(self.disable_url)
        eq_(res.status_code, 302)
        addon = Addon.objects.get(id=3615)
        eq_(addon.disabled_by_user, True)
        eq_(addon.status, amo.STATUS_PUBLIC)
        assert hide_mock.called

        entry = ActivityLog.objects.get()
        eq_(entry.action, amo.LOG.USER_DISABLE.id)
        msg = entry.to_string()
        assert self.addon.name.__unicode__() in msg, ("Unexpected: %r" % msg)

    @mock.patch('devhub.views.unindex_addons')