package com.firma.api.controller;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDSignature;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.http.HttpStatus;
import org.bouncycastle.cms.CMSCertificate;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import java.io.*;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.util.*;

@RestController
public class FirmaController {

    static {
        // Agregar BouncyCastle como proveedor de seguridad
        Security.addProvider(new BouncyCastleProvider());
    }

    @PostMapping("/firma/pdf")
    public ResponseEntity<?> analizarFirma(@RequestParam("archivo") MultipartFile archivo) {
        try {
            // Guardar temporalmente el archivo PDF subido
            File tempFile = File.createTempFile("firma_", ".pdf");
            archivo.transferTo(tempFile);

            // Cargar el documento PDF
            PDDocument document = PDDocument.load(tempFile);
            List<PDSignature> firmas = document.getSignatureDictionaries();

            // Verificar si hay firmas en el documento
            if (firmas.isEmpty()) {
                return ResponseEntity.ok(Map.of("mensaje", "No hay firmas digitales."));
            }

            // Obtener la primera firma (en caso de haber varias)
            PDSignature firma = firmas.get(0);

            // Extraer el certificado de la firma
            byte[] signatureContent = firma.getContents();
            X509Certificate cert = obtenerCertificadoDeFirma(signatureContent);

            // Extraer detalles del certificado
            Map<String, String> certificadoInfo = new HashMap<>();
            certificadoInfo.put("CN", cert.getSubjectX500Principal().getName());
            certificadoInfo.put("SerialNumber", cert.getSerialNumber().toString());
            certificadoInfo.put("Issuer", cert.getIssuerX500Principal().getName());
            certificadoInfo.put("NotBefore", cert.getNotBefore().toString());
            certificadoInfo.put("NotAfter", cert.getNotAfter().toString());

            // Limpieza
            document.close();
            tempFile.delete();

            return ResponseEntity.ok(certificadoInfo);

        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                    .body(Map.of("error", e.getMessage()));
        }
    }

   private X509Certificate obtenerCertificadoDeFirma(byte[] signatureContent) throws Exception {
    // Usar BouncyCastle para extraer el certificado de la firma PKCS7
    ByteArrayInputStream inputStream = new ByteArrayInputStream(signatureContent);
    org.bouncycastle.cms.CMSSignedData signedData = new org.bouncycastle.cms.CMSSignedData(inputStream);

    // Obtener el certificado X.509 de la firma
    Collection<?> certCollection = signedData.getCertificates().getMatches(null);
    if (certCollection.isEmpty()) {
        throw new Exception("No se pudo encontrar el certificado en la firma.");
    }

    // Convertir el certificado a un objeto X509Certificate
    X509CertificateHolder certHolder = (X509CertificateHolder) certCollection.iterator().next();
    JcaX509CertificateConverter converter = new JcaX509CertificateConverter();
    return converter.getCertificate(certHolder);
}
}
