"""user field matcher models"""
import re

from django.db import models
from django.utils.translation import gettext as _
from structlog import get_logger

from passbook.core.models import Policy
from passbook.policies.struct import PolicyRequest, PolicyResult

LOGGER = get_logger()

class FieldMatcherPolicy(Policy):
    """Policy which checks if a field of the User model matches/doesn't match a
    certain pattern"""

    MATCH_STARTSWITH = 'startswith'
    MATCH_ENDSWITH = 'endswith'
    MATCH_CONTAINS = 'contains'
    MATCH_REGEXP = 'regexp'
    MATCH_EXACT = 'exact'

    MATCHES = (
        (MATCH_STARTSWITH, _('Starts with')),
        (MATCH_ENDSWITH, _('Ends with')),
        (MATCH_CONTAINS, _('Contains')),
        (MATCH_REGEXP, _('Regexp')),
        (MATCH_EXACT, _('Exact')),
    )

    USER_FIELDS = (
        ('username', _('Username'),),
        ('name', _('Name'),),
        ('email', _('E-Mail'),),
        ('is_staff', _('Is staff'),),
        ('is_active', _('Is active'),),
        ('data_joined', _('Date joined'),),
    )

    user_field = models.TextField(choices=USER_FIELDS)
    match_action = models.CharField(max_length=50, choices=MATCHES)
    value = models.TextField()

    form = 'passbook.policies.matcher.forms.FieldMatcherPolicyForm'

    def __str__(self):
        description = f"{self.name}, user.{self.user_field} {self.match_action} '{self.value}'"
        if self.name:
            description = f"{self.name}: {description}"
        return description

    def passes(self, request: PolicyRequest) -> PolicyResult:
        """Check if user instance passes this role"""
        if not hasattr(request.user, self.user_field):
            raise ValueError("Field does not exist")
        user_field_value = getattr(request.user, self.user_field, None)
        LOGGER.debug("Checking field", value=user_field_value,
                     action=self.match_action, should_be=self.value)
        passes = False
        if self.match_action == FieldMatcherPolicy.MATCH_STARTSWITH:
            passes = user_field_value.startswith(self.value)
        if self.match_action == FieldMatcherPolicy.MATCH_ENDSWITH:
            passes = user_field_value.endswith(self.value)
        if self.match_action == FieldMatcherPolicy.MATCH_CONTAINS:
            passes = self.value in user_field_value
        if self.match_action == FieldMatcherPolicy.MATCH_REGEXP:
            pattern = re.compile(self.value)
            passes = bool(pattern.match(user_field_value))
        if self.match_action == FieldMatcherPolicy.MATCH_EXACT:
            passes = user_field_value == self.value
        return PolicyResult(passes)

    class Meta:

        verbose_name = _('Field matcher Policy')
        verbose_name_plural = _('Field matcher Policies')