import djconfig
from django.core.exceptions import ValidationError
from django.db import models


class KFetConfig(object):
    """kfet app configuration.

    Enhance isolation with backend used to store config.

    """

    prefix = "kfet_"

    def __init__(self):
        # Set this to False again to reload the config, e.g for testing
        # purposes.
        self._conf_init = False

    def _check_init(self):
        # For initialization purposes, we call 'reload_maybe' directly
        # (normaly done once per request in middleware).
        # Note it should be called only once across requests, if you use
        # kfet_config instance below.
        if not self._conf_init:
            djconfig.reload_maybe()
            self._conf_init = True

    def __getattr__(self, key):
        self._check_init()
        if key == "subvention_cof":
            # Allows accessing to the reduction as a subvention
            # Other reason: backward compatibility
            reduction_mult = 1 - self.reduction_cof / 100
            return (1 / reduction_mult - 1) * 100
        return getattr(djconfig.config, self._get_dj_key(key))

    def list(self):
        """Get list of kfet app configuration.

        Returns:
            (key, value) for each configuration entry as list.

        """
        # prevent circular imports
        from kfet.forms import KFetConfigForm

        self._check_init()
        return [
            (field.label, getattr(djconfig.config, name))
            for name, field in KFetConfigForm.base_fields.items()
        ]

    def _get_dj_key(self, key):
        return "{}{}".format(self.prefix, key)

    def set(self, **kwargs):
        """Update configuration value(s).

        Args:
            **kwargs: Keyword arguments. Keys must be in kfet config.
                Config entries are updated to given values.

        """
        # prevent circular imports
        from kfet.forms import KFetConfigForm

        self._check_init()
        # get old config
        new_cfg = KFetConfigForm().initial
        # update to new config
        for key, value in kwargs.items():
            dj_key = self._get_dj_key(key)
            if isinstance(value, models.Model):
                new_cfg[dj_key] = value.pk
            else:
                new_cfg[dj_key] = value
        # save new config
        cfg_form = KFetConfigForm(new_cfg)
        if cfg_form.is_valid():
            cfg_form.save()
        else:
            raise ValidationError(
                "Invalid values in kfet_config.set: %(fields)s",
                params={"fields": list(cfg_form.errors)},
            )


kfet_config = KFetConfig()