from cryptography.hazmat.primitives.serialization import (
    load_pem_private_key,
    load_ssh_public_key,
)
from cryptography import x509
from django.db.models import TextField
from django.core import exceptions


# ---------------------------------------------------------------------------
class OpenSshPublicKeyField(TextField):
    default_error_messages = {"invalid": "Enter a valid OpenSSH Public Key"}

    def to_python(self, value):
        try:
            load_ssh_public_key(value.encode())
            return value
        except Exception:
            raise exceptions.ValidationError(
                self.error_messages['invalid'],
                code='invalid',
                params={'value': value},
            ) from None


# ---------------------------------------------------------------------------
class PEMCertificateField(TextField):
    def to_python(self, value):
        try:
            x509.load_pem_x509_certificate(value.encode())
            return value
        except Exception:
            raise exceptions.ValidationError(
                self.error_messages['invalid'],
                code='invalid',
                params={'value': value},
            ) from None


# ---------------------------------------------------------------------------
class PEMCertificateRequestField(TextField):
    default_error_messages = {"invalid": "Enter a valid PEM Certificate Request"}

    def to_python(self, value):
        try:
            x509.load_pem_x509_csr(value.encode())
            return value
        except Exception:
            raise exceptions.ValidationError(
                self.error_messages['invalid'],
                code='invalid',
                params={'value': value},
            ) from None


# ---------------------------------------------------------------------------
class PEMPrivateKeyField(TextField):
    default_error_messages = {"invalid": "Enter a valid PEM Private Key"}

    def to_python(self, value):
        try:
            load_pem_private_key(value.encode(), password=None)
            return value
        except Exception:
            raise exceptions.ValidationError(
                self.error_messages['invalid'],
                code='invalid',
                params={'value': value},
            ) from None


__all__ = (
    'OpenSshPublicKeyField',
    'PEMCertificateField',
    'PEMCertificateRequestField',
    'PEMPrivateKeyField',
)
