<?php

namespace Koneko\SatCertificateProcessor\Services;

class SatCertificateProcessorService
{
    /**
     * Convierte datos en DER a PEM.
     *
     * @param string $derData Datos del certificado en formato DER.
     * @param string $type Tipo de certificado (por defecto 'CERTIFICATE').
     * @return string Certificado en formato PEM.
     */
    public function derToPem($derData, $type = "CERTIFICATE")
    {
        $pem = "-----BEGIN $type-----\n";
        $pem .= chunk_split(base64_encode($derData), 64, "\n");
        $pem .= "-----END $type-----\n";
        return $pem;
    }

    /**
     * Extrae informaciĆ³n relevante de un certificado.
     *
     * @param string $certificatePath Ruta al certificado en formato PEM.
     * @return array Datos del certificado (sujeto, fechas de vigencia, fingerprint, etc.).
     * @throws \Exception Si no se puede leer el certificado.
     */
    public function digestCertificate($certificatePath)
    {
        $certContent = file_get_contents($certificatePath);
        if (!$certContent) {
            throw new \Exception("No se pudo leer el certificado en: {$certificatePath}");
        }

        $certData = openssl_x509_parse($certContent);

        $fingerprintRaw = sha1($certContent);
        $fingerprint = strtoupper(implode(":", str_split($fingerprintRaw, 2)));

        return [
            'subject'     => $certData['subject'] ?? null,
            'validFrom'   => date('Y-m-d H:i:s', $certData['validFrom_time_t'] ?? 0),
            'validTo'     => date('Y-m-d H:i:s', $certData['validTo_time_t'] ?? 0),
            'fingerprint' => $fingerprint,
        ];
    }

    /**
     * Firma digitalmente una cadena usando una llave privada.
     *
     * @param string $data Cadena original a firmar.
     * @param string $privateKeyPath Ruta a la llave privada.
     * @param string $passphrase Passphrase de la llave privada.
     * @return string Firma en base64.
     * @throws \Exception Si falla la firma.
     */
    public function signData($data, $privateKeyPath, $passphrase)
    {
        $privateKeyContent = file_get_contents($privateKeyPath);
        $privateKey = openssl_pkey_get_private($privateKeyContent, $passphrase);
        if (!$privateKey) {
            throw new \Exception("No se pudo cargar la llave privada.");
        }

        if (!openssl_sign($data, $signature, $privateKey, OPENSSL_ALGO_SHA256)) {
            throw new \Exception("Error al firmar los datos.");
        }

        return base64_encode($signature);
    }
}