from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
from django.test import TestCase

from wagtail.admin.filters import FilteredModelChoiceField
from wagtail.test.utils import WagtailTestUtils


User = get_user_model()


class TestFilteredModelChoiceField(TestCase, WagtailTestUtils):
    def setUp(self):
        self.musicians = Group.objects.create(name="Musicians")
        self.actors = Group.objects.create(name="Actors")

        self.david = self.create_user(
            'david', 'david@example.com', 'kn1ghtr1der', first_name="David", last_name="Hasselhoff"
        )
        self.david.groups.set([self.musicians, self.actors])

        self.kevin = self.create_user(
            'kevin', 'kevin@example.com', '6degrees', first_name="Kevin", last_name="Bacon"
        )
        self.kevin.groups.set([self.actors])

        self.morten = self.create_user(
            'morten', 'morten@example.com', 't4ke0nm3', first_name="Morten", last_name="Harket"
        )
        self.morten.groups.set([self.musicians])

    def test_with_relation(self):

        class UserForm(forms.Form):
            users = FilteredModelChoiceField(
                queryset=User.objects.order_by(User.USERNAME_FIELD), filter_field='id_group', filter_accessor='groups'
            )

        form = UserForm()
        html = str(form['users'])
        expected_html = """
            <select name="users" data-widget="filtered-select" data-filter-field="id_group" required id="id_users">
                <option value="" selected>---------</option>
                <option value="%(david)s" data-filter-value="%(musicians)s,%(actors)s">%(david_username)s</option>
                <option value="%(kevin)s" data-filter-value="%(actors)s">%(kevin_username)s</option>
                <option value="%(morten)s" data-filter-value="%(musicians)s">%(morten_username)s</option>
            </select>
        """ % {
            'david': self.david.pk, 'kevin': self.kevin.pk, 'morten': self.morten.pk,
            'musicians': self.musicians.pk, 'actors': self.actors.pk,
            'david_username': self.david.get_username(), 'kevin_username': self.kevin.get_username(),
            'morten_username': self.morten.get_username(),
        }
        self.assertHTMLEqual(html, expected_html)

    def test_with_callable(self):

        class UserForm(forms.Form):
            users = FilteredModelChoiceField(
                queryset=User.objects.order_by(User.USERNAME_FIELD), filter_field='id_group',
                filter_accessor=lambda user: user.groups.all()
            )

        form = UserForm()
        html = str(form['users'])
        expected_html = """
            <select name="users" data-widget="filtered-select" data-filter-field="id_group" required id="id_users">
                <option value="" selected>---------</option>
                <option value="%(david)s" data-filter-value="%(musicians)s,%(actors)s">%(david_username)s</option>
                <option value="%(kevin)s" data-filter-value="%(actors)s">%(kevin_username)s</option>
                <option value="%(morten)s" data-filter-value="%(musicians)s">%(morten_username)s</option>
            </select>
        """ % {
            'david': self.david.pk, 'kevin': self.kevin.pk, 'morten': self.morten.pk,
            'musicians': self.musicians.pk, 'actors': self.actors.pk,
            'david_username': self.david.get_username(), 'kevin_username': self.kevin.get_username(),
            'morten_username': self.morten.get_username(),
        }
        self.assertHTMLEqual(html, expected_html)
