import re

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Row, Fieldset, Div
from django import forms
from django.contrib.auth.models import User as django_user
from django.utils.translation import gettext_lazy as _, pgettext
from rolepermissions.roles import RolesManager

from accounts import crispy_layouts
from accounts.consts import FIFA_PROXY_TYPE_NAME, DELETE_CONSOLE_REASON, CONSOLE_USER_MODE
from accounts.models import FifaAccount, InvestorOperators, Console
from customrolepermissions.permissions import has_permission_exactly
from utils.buttons import ButtonSubmit
from utils.encrypting import get_encrypter
from utils.select2_form_fields import Select2Widget


class UserPermissionForm(forms.Form):
    is_active = forms.BooleanField(label='Is Active', required=False)

    perm_encrypter = get_encrypter()

    def __init__(self, *args, **kwargs):
        available_permissions = kwargs.pop('available_permissions', [])
        possible_permissions = kwargs.pop('possible_permissions', [])
        grant_permissions = kwargs.pop('grant_permissions', [])

        kwargs.setdefault('initial', {})
        kwargs['initial'].update(dict(
            (self.perm_encrypter.encrypt(permission), (permission in available_permissions))
            for permission in possible_permissions
        ))

        super().__init__(*args, **kwargs)

        for permission in possible_permissions:
            if permission in grant_permissions:
                widget = forms.CheckboxInput(attrs={'disabled': True})
            else:
                widget = None  # default

            label = pgettext('permission', permission)
            if label == permission:
                label = self.auto_label(permission)
            field_name = self.perm_encrypter.encrypt(permission)
            self.fields[field_name] = forms.BooleanField(label=label, required=False, widget=widget)

        self.helper = None
        self.build_formhelper()

    def build_formhelper(self):
        permission_field_names = list(self.fields.keys())
        permission_field_names.remove('is_active')

        self.helper = FormHelper()
        self.helper.layout = Layout(
            Row(
                Fieldset(
                    _('User Status'),
                    Div(
                        'is_active',
                        css_class='auto-multi-column-inner',
                    ),
                    css_class='small-12',
                ),
                css_class='auto-multi-column columns',
            ),
            Row(
                Fieldset(
                    _('Permissions'),
                    Div(
                        *permission_field_names,
                        css_class='auto-multi-column-inner',
                    ),
                ),
                css_class='auto-multi-column columns',
            ),
            Row(
                ButtonSubmit('submit', _('Update Permissions'), css_class='btn-primary mdi mdi-account-key'),
                css_class='col',
            )
        )

    def clean(self):
        c = self.cleaned_data

        encrypted_keys = list(self.cleaned_data.keys())
        encrypted_keys.remove('is_active')

        for encrypted_key in encrypted_keys:
            value = c.pop(encrypted_key, False)
            permission = UserPermissionForm.perm_encrypter.decrypt(encrypted_key)
            c[permission] = value

    WHO_MAP = {
        'all': 'every',
        'rel': 'relevant',
        'own': 'own',
    }
    split_re = re.compile(r'[_]+')

    def auto_label(self, permission):
        segments = self.split_re.split(permission)

        who = ''
        if segments[-1] in ['all', 'rel', 'own']:
            who = segments.pop(-1)

        action = ''
        if segments[-1] in ['create', 'read', 'update', 'delete', 'view']:
            action = segments.pop(-1)

        if who:
            segments.insert(0, self.WHO_MAP.get(who, who))

        if action:
            segments.insert(0, action)

        label = ' '.join(segments)
        label = label.capitalize()
        return label


class UserRoleForm(forms.Form):
    roles = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple, required=False)
    helper = crispy_layouts.UserRoleFormHelper()

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        sorted_roles = sorted(RolesManager.get_roles(), key=lambda r: getattr(r, 'order', 10000))
        self.fields['roles'].choices = [
            (role.get_name(), role.verbose_name)
            for role in sorted_roles
            if getattr(role, 'selectable_role', True)
        ]


class FifaAccountUpdateForm(forms.ModelForm):
    helper = crispy_layouts.FifaAccountUpdateFormHelper()

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['credit'].disabled = True
        self.fields['platform'].disabled = True
        self.fields['name_in_console'].disabled = True
        self.fields['use_request_login'].disabled = True
        self.fields['use_special_squad'].disabled = True
        self.fields['special_squad_ready_to_play'].disabled = True
        self.fields['stop_for_update_game'].disabled = True
        # self.fields['allowed_play_game'].disabled = True
        # self.fields['allowed_play_game_day'].disabled = True

    class Meta:
        model = FifaAccount
        fields = ['console', 'run_force_discharge', 'password', 'proxy', 'xbox_pass', 'credit', 'platform',
                  'name_in_console',
                  'use_request_login', 'use_special_squad', 'special_squad_ready_to_play',
                  'allowed_play_game', 'allowed_play_game_day', 'squad_special_game_one', 'squad_special_game_two',
                  'need_captcha', 'stop_for_update_game']


class MuleAccountFileCreateForm(forms.Form):
    mule_file = forms.FileField()
    # console__investor__investor_operator_user__operators__id
    investors = forms.ModelMultipleChoiceField(
        queryset=InvestorOperators.objects.filter(operators__in=[]),
        required=False,
    )
    helper = crispy_layouts.MuleAccountFileCreateFormHelper()

    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user')
        super().__init__(*args, **kwargs)
        if has_permission_exactly(user, 'mule_accounts__read__all'):
            self.fields['investors'].queryset = django_user.objects.filter(
                id__in=InvestorOperators.objects.values_list('investor__id', flat=True)
            )
        else:
            self.fields['investors'].queryset = django_user.objects.filter(
                id__in=InvestorOperators.objects.filter(
                    operators__in=[user]).values_list('investor__id', flat=True)
            )

    class Meta:
        fields = ['mule_file', 'investors']


class FifaProxyCreateForm(forms.Form):
    proxy_file = forms.FileField()
    type_name = forms.CharField(
        widget=Select2Widget(
            choices=FIFA_PROXY_TYPE_NAME,
            attrs={
                'data-placeholder': _('------'),
            },
        ), required=False,
    )
    helper = crispy_layouts.FifaProxyCreateFormHelper()

    class Meta:
        fields = ['proxy_file', 'type_name']


class FifaAccountSpecialProxyForm(forms.Form):
    accounts_file = forms.FileField()
    type_name = forms.CharField(
        widget=Select2Widget(
            choices=FIFA_PROXY_TYPE_NAME,
            attrs={
                'data-placeholder': _('------'),
            },
        ), required=False,
    )
    remove_old_proxy = forms.BooleanField(label='Remove Old', required=False)
    helper = crispy_layouts.FifaAccountSpecialProxyFormHelper()

    class Meta:
        fields = ['accounts_file', 'type_name', 'remove_old_proxy']


class ConsoleUpdateForm(forms.ModelForm):
    helper = crispy_layouts.ConsoleUpdateFormHelper()

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['allowed_play_game_day'].disabled = True
        self.fields['need_games_update'].disabled = True
        self.fields['allowed_account_work_day'].disabled = True

    class Meta:
        model = Console
        fields = ['allowed_play_game_day', 'need_games_update', 'allowed_account_work_day', 'turn_off_after_work']


class SimpleFileUploadForm(forms.Form):
    upload_file = forms.FileField()
    helper = crispy_layouts.SimpleFileUploadFormHelper()

    class Meta:
        fields = ['upload_file', 'type_name']


class AddAccountsViewForm(SimpleFileUploadForm):
    delete_console_reason = forms.ChoiceField(
        choices=[('-1', '---')] + list(DELETE_CONSOLE_REASON), initial='-1', required=False, widget=Select2Widget)
    console_user_mode = forms.ChoiceField(
        choices=list(CONSOLE_USER_MODE), initial=0, required=False, widget=Select2Widget)
    helper = crispy_layouts.AddAccountsViewFormHelper()

    class Meta:
        fields = ['upload_file', 'delete_console_reason', 'console_user_mode']


class ConsoleFileFilterForm(forms.Form):
    range_number_min = forms.CharField(required=False, label="Console Range min")
    range_number_max = forms.CharField(required=False, label="Range max")
    upload_file = forms.FileField(required=False, label="Excel File")

    helper = crispy_layouts.ConsoleFileListFilterHelper()


class ConsoleAccountManagementForm(forms.Form):
    upload_file = forms.FileField(label="Upload File", required=True)
    action = forms.ChoiceField(
        choices=[('1', 'Add Data'), ('2', 'Remove Data')],
        label="Action",
        required=True,
        widget=Select2Widget
    )

    helper = crispy_layouts.ConsoleAccountManagementFormHelper()
