import copy

from django.utils.translation import gettext_lazy as _
from rest_framework import serializers

from accounts.const import SecretType, DEFAULT_PASSWORD_RULES
from common.utils import ssh_key_gen, random_string
from common.utils import validate_ssh_private_key, parse_ssh_private_key_str


class SecretGenerator:
    def __init__(self, secret_strategy, secret_type, password_rules=None):
        self.secret_strategy = secret_strategy
        self.secret_type = secret_type
        self.password_rules = password_rules

    @staticmethod
    def generate_ssh_key():
        private_key, __ = ssh_key_gen()
        return private_key

    def generate_password(self):
        password_rules = self.password_rules
        if not password_rules or not isinstance(password_rules, dict):
            password_rules = {}
        rules = copy.deepcopy(DEFAULT_PASSWORD_RULES)
        rules.update(password_rules)
        rules = {
            'length': rules['length'],
            'lower': rules['lowercase'],
            'upper': rules['uppercase'],
            'digit': rules['digit'],
            'special_char': rules['symbol'],
            'exclude_chars': rules.get('exclude_symbols', ''),
        }
        return random_string(**rules)

    def get_secret(self):
        if self.secret_type == SecretType.SSH_KEY:
            secret = self.generate_ssh_key()
        elif self.secret_type == SecretType.PASSWORD:
            secret = self.generate_password()
        else:
            raise ValueError("Secret must be set")
        return secret


def validate_password_for_ansible(password):
    """ 校验 Ansible 不支持的特殊字符 """
    if password.startswith('{{') and password.endswith('}}'):
        raise serializers.ValidationError(
            _('If the password starts with {{` and ends with }} `, then the password is not allowed.')
        )


def validate_ssh_key(ssh_key, passphrase=None):
    valid = validate_ssh_private_key(ssh_key, password=passphrase)
    if not valid:
        raise serializers.ValidationError(_("private key invalid or passphrase error"))
    return parse_ssh_private_key_str(ssh_key, passphrase)