"""
This module provides a simple interface for generating RSA key pairs
"""

import os

from cryptography import x509
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.backends import default_backend


def generate_private_key(key_path: str):
    """Generate a new RSA private key and save it to a file."""

    private_key = rsa.generate_private_key(
        public_exponent=65537,
        key_size=4096,
    )

    pem_private_key = private_key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.PKCS8,
        encryption_algorithm=serialization.NoEncryption(),
    )

    with open(key_path, "wb") as f:
        f.write(pem_private_key)

    os.chmod(key_path, 0o700)

    return pem_private_key


# pylint: disable=too-many-arguments,too-many-positional-arguments
def generate_csr_from_private_key(
    private_key_content: bytes,
    country: str,
    state: str,
    locality: str,
    organization: str,
    common_name: str,
) -> str:
    """
    Generate a CSR (Certificate Signing Request) from an existing private key.
    Returns:
        str: The generated CSR in PEM format.
    """

    private_key = serialization.load_pem_private_key(
        private_key_content,
        password=None,
        backend=default_backend(),
    )

    csr_builder = x509.CertificateSigningRequestBuilder()
    csr_builder = (
        csr_builder.subject_name(
            x509.Name(
                [
                    x509.NameAttribute(NameOID.COUNTRY_NAME, country),
                    x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, state),
                    x509.NameAttribute(NameOID.LOCALITY_NAME, locality),
                    x509.NameAttribute(NameOID.ORGANIZATION_NAME, organization),
                    x509.NameAttribute(NameOID.COMMON_NAME, common_name),
                ]
            )
        )
        .add_extension(
            x509.BasicConstraints(ca=False, path_length=None),
            critical=False,
        )
        .add_extension(
            x509.UnrecognizedExtension(
                x509.ObjectIdentifier("2.16.840.1.113730.1.1"),
                b"SSL Client, S/MIME",
            ),
            critical=False,
        )
        .add_extension(
            x509.UnrecognizedExtension(
                x509.ObjectIdentifier("2.16.840.1.113730.1.13"),
                b"Generated by OBS/OCD",
            ),
            critical=False,
        )
        .add_extension(
            x509.KeyUsage(
                digital_signature=True,
                crl_sign=False,
                key_encipherment=True,
                content_commitment=True,
                data_encipherment=False,
                key_agreement=False,
                key_cert_sign=False,
                encipher_only=False,
                decipher_only=False,
            ),
            critical=True,
        )
        .add_extension(
            x509.ExtendedKeyUsage(
                [
                    x509.ExtendedKeyUsageOID.CLIENT_AUTH,
                    x509.ExtendedKeyUsageOID.EMAIL_PROTECTION,
                ]
            ),
            critical=False,
        )
    )

    csr = csr_builder.sign(private_key, hashes.SHA256())
    return csr.public_bytes(serialization.Encoding.PEM).decode("utf-8")
