"""Ajustes de vigencia para certificados emitidos por OpenSSL."""

import ssl
import subprocess
from datetime import timedelta, timezone

from pyasn1.codec.der.decoder import decode
from pyasn1.codec.der.encoder import encode
from pyasn1.type import univ, useful


def backdate_not_before(crt_path, ca_key_path):
    """Adelanta solo notBefore cinco minutos y vuelve a firmar el certificado."""
    certificate, remainder = decode(
        ssl.PEM_cert_to_DER_cert(crt_path.read_text())
    )
    if remainder:
        raise ValueError("Datos inesperados después del certificado")

    tbs_certificate = certificate[0]
    # TBSCertificate puede comenzar con la versión explícita o con el serial.
    validity_index = (
        3 if tbs_certificate[0].tagSet == univ.Integer.tagSet else 4
    )
    validity = tbs_certificate[validity_index]

    # OpenSSL ya usó un único instante UTC, expresado con precisión de segundos.
    # Se reutiliza ese instante; notAfter queda byte por byte sin modificar.
    now = validity[0].asDateTime.astimezone(timezone.utc)
    not_before = now - timedelta(minutes=5)
    if 1950 <= not_before.year < 2050:
        encoded_time = useful.UTCTime(not_before.strftime("%y%m%d%H%M%SZ"))
    else:
        encoded_time = useful.GeneralizedTime(
            not_before.strftime("%Y%m%d%H%M%SZ")
        )
    validity.setComponentByPosition(
        0,
        encoded_time,
        verifyConstraints=False,
        matchTags=False,
        matchConstraints=False,
    )

    # El certificado original usa SHA-256; la misma clave de CA vuelve a firmar
    # únicamente porque cualquier cambio en notBefore invalida la firma anterior.
    signature = subprocess.run(
        ["openssl", "dgst", "-sha256", "-sign", str(ca_key_path)],
        input=encode(tbs_certificate),
        capture_output=True,
        check=True,
    ).stdout
    certificate[2] = univ.BitString.fromOctetString(signature)

    # Escribir solo después de que la firma terminó correctamente.
    crt_path.write_text(ssl.DER_cert_to_PEM_cert(encode(certificate)))
