<?php

namespace App\Services;

use TCPDF;

/**
 * Servicio de PDF
 * Generación de contratos firmados con evidencias y certificación legal
 */
class PDFService
{
    private Logger $logger;
    private SecurityService $security;
    private string $storagePath;

    // Paleta corporativa
    private array $colorBlue   = [29,  78,  216]; // indigo-700
    private array $colorGreen  = [22,  163,  74]; // green-600
    private array $colorGray   = [107, 114, 128]; // gray-500
    private array $colorLight  = [243, 244, 246]; // gray-100
    private array $colorBorder = [209, 213, 219]; // gray-300
    private array $colorBlack  = [17,  24,  39];  // gray-900
    private array $colorRed    = [185,  28,  28]; // red-700
    private array $colorDark   = [31,  41,  55];  // gray-800

    // Layout
    private float $marginL  = 16;
    private float $marginR  = 16;
    private float $pageW    = 210;
    private float $contentW = 178; // 210 - 16 - 16

    // Alturas de header/footer
    private float $headerH = 22;
    private float $footerH = 12;

    public function __construct()
    {
        $this->logger      = new Logger();
        $this->security    = new SecurityService();
        $this->storagePath = storage_path();
    }

    // =========================================================================
    // GENERACIÓN PRINCIPAL
    // =========================================================================

    public function generateSignedContract(array $contract, array $signature): string
    {
        try {
            require_once config_path('company-data.php');

            $meta   = [];
            if (!empty($signature['metadata'])) {
                $meta = json_decode($signature['metadata'], true) ?? [];
            }

            $hashes = $this->computeEvidenceHashes($signature);

            // Subclase anónima de TCPDF que sobreescribe Header() y Footer()
            // para dibujarlos en TODAS las páginas, incluyendo las creadas
            // automáticamente por auto page break dentro de writeHTML.
            $titleHolder = (object)['value' => ''];
            $svcRef      = $this;
            $sigRef      = $signature;
            $contractRef = $contract;

            $pdf = new class($titleHolder, $svcRef, $sigRef, $contractRef) extends TCPDF {
                private object $th;
                private object $svc;
                private array  $sig;
                private array  $contract;

                public function __construct(object $th, object $svc, array $sig, array $contract) {
                    parent::__construct('P', 'mm', 'A4', true, 'UTF-8', false);
                    $this->th       = $th;
                    $this->svc      = $svc;
                    $this->sig      = $sig;
                    $this->contract = $contract;
                }

                public function Header(): void {
                    $this->svc->drawHeader($this, $this->th->value, $this->contract);
                }

                public function Footer(): void {
                    $this->svc->drawFooterStatic($this, $this->sig, $this->contract);
                }
            };

            $pdf->SetCreator('Sistema de Contratos Digitales - ' . COMPANY_NAME);
            $pdf->SetAuthor($contract['cliente_nombre'] ?? 'Sistema');
            $pdf->SetTitle('Contrato Firmado: ' . $contract['titulo']);
            $pdf->SetSubject('Contrato Digital con Firma Electrónica');
            $pdf->SetKeywords('contrato, firma digital, evidencia');

            $pdf->setPrintHeader(true);
            $pdf->setPrintFooter(true);
            $pdf->setHeaderMargin(0);
            $pdf->setFooterMargin(0);
            $pdf->SetMargins($this->marginL, $this->headerH + 6, $this->marginR);
            $pdf->SetAutoPageBreak(true, $this->footerH + 6);

            // Páginas — actualizar $titleHolder->value antes de cada AddPage
            $titleHolder->value = 'CONTRATO DIGITAL FIRMADO';
            $pdf->AddPage();
            $this->pageContract($pdf, $contract, $signature);

            $titleHolder->value = 'INFORMACIÓN DEL CLIENTE';
            $pdf->AddPage();
            $this->pageClientInfo($pdf, $contract, $signature, $meta);

            $titleHolder->value = 'DATOS DEL FIRMANTE';
            $pdf->AddPage();
            $this->pageSignerData($pdf, $contract, $signature, $meta);

            $titleHolder->value = 'EVIDENCIAS VISUALES';
            $pdf->AddPage();
            $this->pageEvidences($pdf, $signature);

            $titleHolder->value = 'CERTIFICACIÓN DE AUTENTICIDAD';
            $pdf->AddPage();
            $this->pageCertification($pdf, $contract, $signature, $hashes, $meta);

            $titleHolder->value = 'VALIDACIÓN DEL DOCUMENTO';
            $pdf->AddPage();
            $this->pageValidation($pdf, $contract, $signature);

            // Guardar
            $timestamp    = time();
            $filename     = "contract_{$contract['id']}_signed_{$timestamp}.pdf";
            $relativePath = "contracts/{$filename}";
            $fullPath     = $this->storagePath . '/' . $relativePath;

            $dir = dirname($fullPath);
            if (!is_dir($dir)) mkdir($dir, 0755, true);

            $pdf->Output($fullPath, 'F');

            $pdfHash = hash_file('sha256', $fullPath);

            $db = Database::getInstance();
            $db->update(
                'signatures',
                ['pdf_path' => $relativePath, 'pdf_hash' => $pdfHash],
                'id = :id',
                [':id' => $signature['id']]
            );

            $this->logger->info("PDF generated for contract #{$contract['id']}: {$relativePath}");

            return $relativePath;
        } catch (\Exception $e) {
            $this->logger->error('Error generating PDF: ' . $e->getMessage());
            throw new \Exception('Error al generar el PDF del contrato.');
        }
    }

    // =========================================================================
    // PÁGINA 1 — CONTENIDO DEL CONTRATO
    // =========================================================================

    private function pageContract(TCPDF $pdf, array $contract, array $signature): void
    {
        // Caja resumen del contrato
        $this->infoBox($pdf, [
            'ID del contrato' => sprintf('#%06d', $contract['id']),
            'Título'          => $contract['titulo'],
            'Fecha de firma'  => date('d/m/Y H:i:s', strtotime($signature['firmado_at'])),
            'Firmado por'     => $signature['nombre_completo'] ?? $contract['cliente_nombre'],
        ]);

        $pdf->Ln(3);
        $this->sectionTitle($pdf, 'Contenido del Contrato');

        $pdf->SetFont('dejavusans', '', 10.5);
        $pdf->SetTextColor(...$this->colorBlack);
        $pdf->setCellHeightRatio(1.3);
        $contenido = $this->sanitizeHtmlForPdf($contract['contenido']);
        $pdf->writeHTML($contenido, true, false, true, false, '');
    }

    // =========================================================================
    // PÁGINA 2 — INFORMACIÓN DEL CLIENTE
    // =========================================================================

    private function pageClientInfo(TCPDF $pdf, array $contract, array $signature, array $meta): void
    {
        $this->sectionTitle($pdf, 'Datos del Cliente');

        $clientRows = [
            'Nombre del cliente' => $contract['cliente_nombre'],
            'Email'              => !empty($contract['cliente_email']) ? $contract['cliente_email'] : 'No proporcionado',
        ];
        if (!empty($contract['cliente_telefono'])) {
            $clientRows['Teléfono'] = '+' . ltrim($contract['cliente_telefono'], '+');
        }
        $this->dataTable($pdf, $clientRows);

        $pdf->Ln(5);
        $this->sectionTitle($pdf, 'Detalles del Contrato');

        $contractRows = [
            'ID del contrato'     => sprintf('#%06d', $contract['id']),
            'Título'              => $contract['titulo'],
            'Fecha de creación'   => date('d/m/Y H:i:s', strtotime($contract['created_at'])),
            'Fecha de firma'      => date('d/m/Y H:i:s', strtotime($signature['firmado_at'])),
            'Estado'              => ucfirst($contract['estado']),
        ];
        if (!empty($contract['expira_at'])) {
            $contractRows['Fecha de expiración'] = date('d/m/Y H:i:s', strtotime($contract['expira_at']));
        }
        $this->dataTable($pdf, $contractRows);

        $pdf->Ln(5);
        $this->sectionTitle($pdf, 'Resumen del Contrato');

        $pdf->SetFont('dejavusans', '', 9.5);
        $pdf->SetTextColor(...$this->colorGray);

        $resumen = strip_tags($contract['contenido']);
        if (strlen($resumen) > 900) {
            $resumen = substr($resumen, 0, 900) . '…';
        }
        $pdf->MultiCell($this->contentW, 5.5, $resumen, 0, 'J', false);

        $pdf->Ln(4);
        $this->sectionTitle($pdf, 'Documentos Entregados al Cliente');

        $email = !empty($contract['cliente_email']) ? $contract['cliente_email'] : 'no especificado';
        $this->dataTable($pdf, [
            'PDF certificado'        => 'Este documento — contrato, evidencias, hashes SHA-256 y código de verificación.',
            'Correo de confirmación' => 'Enviado a ' . $email . ' con el PDF adjunto.',
            'Código de verificación' => 'Permite validar la autenticidad del documento en línea en cualquier momento.',
        ]);
    }

    // =========================================================================
    // PÁGINA 3 — DATOS DEL FIRMANTE
    // =========================================================================

    private function pageSignerData(TCPDF $pdf, array $contract, array $signature, array $meta): void
    {
        $this->sectionTitle($pdf, 'Información Personal');

        $nombre   = $signature['nombre_completo']  ?? ($meta['nombre_completo']  ?? $contract['cliente_nombre']);
        $fechaNac = $signature['fecha_nacimiento'] ?? ($meta['fecha_nacimiento'] ?? null);
        $fechaExp = $signature['fecha_expedicion'] ?? ($meta['fecha_expedicion'] ?? null);
        $telefono = $signature['telefono']         ?? ($meta['telefono']         ?? $contract['cliente_telefono'] ?? null);

        $this->dataTable($pdf, [
            'Nombre completo'      => $nombre,
            'Tipo de documento'    => $signature['tipo_documento'],
            'Número de documento'  => $signature['numero_documento'],
            'Fecha de nacimiento'  => $fechaNac ? date('d/m/Y', strtotime($fechaNac)) : '—',
            'Fecha de expedición'  => $fechaExp ? date('d/m/Y', strtotime($fechaExp)) : '—',
            'Email'                => $contract['cliente_email'] ?? '—',
            'Teléfono'             => $telefono ? '+' . ltrim($telefono, '+') : '—',
        ]);

        $pdf->Ln(5);
        $this->sectionTitle($pdf, 'Datos Técnicos de la Firma');

        $techRows = [
            'Fecha y hora de firma'  => date('d/m/Y H:i:s', strtotime($signature['firmado_at'])),
            'Zona horaria'           => $meta['timezone']  ?? '—',
            'Dirección IP'           => $signature['ip_address'],
            'Idioma del dispositivo' => $meta['language']  ?? '—',
            'Resolución de pantalla' => (!empty($meta['screen_width']) && !empty($meta['screen_height']))
                                        ? "{$meta['screen_width']} × {$meta['screen_height']} px" : '—',
        ];
        if ($signature['ubicacion_lat'] && $signature['ubicacion_lng']) {
            $techRows['Coordenadas GPS'] = sprintf(
                '%.6f, %.6f (±%dm)',
                $signature['ubicacion_lat'],
                $signature['ubicacion_lng'],
                $signature['ubicacion_precision'] ?? 0
            );
        }
        $techRows['User-Agent'] = substr($signature['user_agent'] ?? '—', 0, 90);
        $this->dataTable($pdf, $techRows);

        $pdf->Ln(5);
        $this->sectionTitle($pdf, 'Firma Digital Manuscrita');

        $firmaPath = $this->storagePath . '/' . ($signature['firma_imagen_path'] ?? '');
        if (file_exists($firmaPath)) {
            $y = $pdf->GetY();
            $pdf->SetFillColor(255, 255, 255);
            $pdf->SetDrawColor(...$this->colorBorder);
            $pdf->SetLineWidth(0.3);
            $pdf->RoundedRect($this->marginL, $y, $this->contentW, 38, 2, '1111', 'FD');
            $pdf->Image($firmaPath, ($this->pageW / 2) - 40, $y + 3, 80, 32, '', '', '', false, 300, '', false, false, 0);
            $pdf->Ln(42);
        } else {
            $this->warningBox($pdf, 'Imagen de firma no disponible.');
        }
    }

    // =========================================================================
    // PÁGINA 4 — EVIDENCIAS VISUALES
    // =========================================================================

    private function pageEvidences(TCPDF $pdf, array $signature): void
    {
        $cW = $this->contentW;
        $mL = $this->marginL;

        // ── Selfie ────────────────────────────────────────────────────────────
        $this->sectionTitle($pdf, 'Fotografía del Firmante (Selfie)');
        $selfiePath = $this->storagePath . '/' . ($signature['selfie_path'] ?? '');
        if (file_exists($selfiePath)) {
            $yS = $pdf->GetY();
            $pdf->Image($selfiePath, ($this->pageW / 2) - 36, $yS, 72, 58, '', '', '', false, 300, '', false, false, 1);
            $pdf->Ln(63);
        } else {
            $this->placeholderBox($pdf, $mL, $pdf->GetY(), $cW, 58, 'Selfie no disponible');
            $pdf->Ln(63);
        }

        $pdf->Ln(2);

        // ── Documentos en 2 columnas ─────────────────────────────────────────
        $this->sectionTitle($pdf, 'Documento de Identidad');

        $colW  = ($cW - 4) / 2;
        $yDoc  = $pdf->GetY();
        $imgH  = 55;

        // Etiquetas
        $pdf->SetFont('dejavusans', 'B', 7.5);
        $pdf->SetTextColor(...$this->colorGray);
        $pdf->SetXY($mL, $yDoc);
        $pdf->Cell($colW, 5, 'CARA FRONTAL', 0, 0, 'C');
        $pdf->SetXY($mL + $colW + 4, $yDoc);
        $pdf->Cell($colW, 5, 'CARA TRASERA', 0, 0, 'C');

        $yImg = $yDoc + 5;

        $frontPath = $this->storagePath . '/' . ($signature['documento_frontal_path'] ?? '');
        if (file_exists($frontPath)) {
            $pdf->Image($frontPath, $mL, $yImg, $colW, $imgH, '', '', '', false, 300, '', false, false, 1);
        } else {
            $this->placeholderBox($pdf, $mL, $yImg, $colW, $imgH, 'No disponible');
        }

        $backPath = $this->storagePath . '/' . ($signature['documento_trasero_path'] ?? '');
        if (file_exists($backPath)) {
            $pdf->Image($backPath, $mL + $colW + 4, $yImg, $colW, $imgH, '', '', '', false, 300, '', false, false, 1);
        } else {
            $this->placeholderBox($pdf, $mL + $colW + 4, $yImg, $colW, $imgH, 'No disponible');
        }

        $pdf->SetY($yImg + $imgH + 4);
    }

    // =========================================================================
    // PÁGINA 5 — CERTIFICACIÓN Y HASHES
    // =========================================================================

    private function pageCertification(TCPDF $pdf, array $contract, array $signature, array $hashes, array $meta): void
    {
        $cW = $this->contentW;
        $mL = $this->marginL;

        // Sello de certificación
        $y0 = $pdf->GetY();
        $pdf->SetFillColor(237, 242, 255);
        $pdf->SetDrawColor(...$this->colorBlue);
        $pdf->SetLineWidth(0.8);
        $pdf->RoundedRect($mL, $y0, $cW, 26, 3, '1111', 'FD');

        $pdf->SetFont('helvetica', 'B', 11);
        $pdf->SetTextColor(...$this->colorBlue);
        $pdf->SetXY($mL, $y0 + 4);
        $pdf->Cell($cW, 7, 'DOCUMENTO CON VALIDEZ LEGAL', 0, 1, 'C');

        $pdf->SetFont('dejavusans', '', 8.5);
        $pdf->SetTextColor(...$this->colorGray);
        $pdf->SetX($mL);
        $pdf->MultiCell(
            $cW, 4.5,
            "Este contrato fue firmado electrónicamente con plena aceptación del firmante.\n" .
            "Identidad verificada mediante documento de identidad y biometría facial.\n" .
            "Timestamp: " . date('d/m/Y H:i:s T', strtotime($signature['firmado_at'])),
            0, 'C'
        );

        $pdf->Ln(5);
        $pdf->SetLineWidth(0.2);

        // Hashes SHA-256
        $this->sectionTitle($pdf, 'Hashes de Integridad SHA-256');

        $hashRows = [];
        foreach ($hashes as $label => $hash) {
            $hashRows[$label] = $hash ?: '(archivo no disponible)';
        }
        $this->hashTable($pdf, $hashRows);

        $pdf->Ln(4);
        $this->sectionTitle($pdf, 'Identificadores del Registro');

        $this->dataTable($pdf, [
            'ID del contrato' => sprintf('#%06d', $contract['id']),
            'ID de firma'     => sprintf('#%06d', $signature['id']),
            'Firmado el'      => date('d/m/Y H:i:s', strtotime($signature['firmado_at'])),
            'IP del firmante' => $signature['ip_address'],
            'Documento'       => $signature['tipo_documento'] . ': ' . $signature['numero_documento'],
        ]);

        $pdf->Ln(4);
        $this->sectionTitle($pdf, 'Declaración Legal');

        $pdf->SetFont('dejavusans', 'I', 8.5);
        $pdf->SetTextColor(...$this->colorGray);
        $pdf->SetFillColor(249, 250, 251);
        $pdf->MultiCell(
            $cW, 5,
            "El firmante declara haber leído y aceptado íntegramente el contrato de forma libre y voluntaria. " .
            "Este documento tiene plena validez jurídica conforme a la legislación vigente sobre comercio " .
            "electrónico y firma digital. Los hashes SHA-256 permiten verificar que ningún elemento ha sido " .
            "alterado desde el momento de la firma.",
            1, 'J', true, 1
        );
    }

    // =========================================================================
    // PÁGINA 6 — VALIDACIÓN DEL DOCUMENTO
    // =========================================================================

    private function pageValidation(TCPDF $pdf, array $contract, array $signature): void
    {
        $cW = $this->contentW;
        $mL = $this->marginL;

        // Guardar posición antes del watermark (Text() mueve el cursor)
        $yStart = $pdf->GetY();

        // Watermark decorativo
        $pdf->SetAlpha(0.06);
        $pdf->SetFont('dejavusans', 'B', 65);
        $pdf->SetTextColor(29, 78, 216);
        $pdf->StartTransform();
        $pdf->Rotate(45, 105, 148);
        $pdf->Text(30, 150, 'VÁLIDO');
        $pdf->StopTransform();
        $pdf->SetAlpha(1);

        // Restaurar posición al tope del contenido
        $pdf->SetY($yStart);

        // Caja DOCUMENTO VERIFICADO
        $y = $pdf->GetY();
        $pdf->SetFillColor(240, 253, 244);
        $pdf->SetDrawColor(34, 197, 94);
        $pdf->SetLineWidth(1.5);
        $pdf->RoundedRect($mL, $y, $cW, 42, 4, '1111', 'FD');

        $pdf->SetFont('dejavusans', 'B', 13);
        $pdf->SetTextColor(22, 163, 74);
        $pdf->SetXY($mL, $y + 6);
        $pdf->Cell($cW, 7, 'DOCUMENTO VERIFICADO', 0, 1, 'C');

        $pdf->SetFont('dejavusans', '', 9);
        $pdf->SetTextColor(21, 128, 61);
        $pdf->SetX($mL);
        $pdf->Cell($cW, 5, 'Este documento ha sido firmado electrónicamente y es válido', 0, 1, 'C');
        $pdf->Ln(2);

        $verificationCode = strtoupper(substr(
            hash('sha256', $contract['id'] . $signature['id'] . $signature['firmado_at']),
            0, 16
        ));
        $codeDisplay = implode('-', str_split($verificationCode, 4));

        $pdf->SetFont('dejavusans', 'B', 12);
        $pdf->SetTextColor(22, 163, 74);
        $pdf->SetX($mL);
        $pdf->Cell($cW, 6, 'Código: ' . $codeDisplay, 0, 1, 'C');

        $pdf->Ln(3);

        // URL de verificación
        $verifyUrl = rtrim($_ENV['APP_URL'] ?? 'https://tucontrato.online', '/') . '/verificar';

        $pdf->SetFont('dejavusans', 'B', 9);
        $pdf->SetTextColor(...$this->colorBlue);
        $pdf->Cell(0, 5, 'Verifica este documento en:', 0, 1, 'C');
        $pdf->SetFont('dejavusans', '', 9.5);
        $pdf->Cell(0, 5, $verifyUrl, 0, 1, 'C');
        $pdf->Ln(6);

        // Instrucciones
        $this->sectionTitle($pdf, 'Cómo Verificar Este Documento');

        $pdf->SetFont('dejavusans', '', 9.5);
        $pdf->SetTextColor(...$this->colorBlack);

        $steps = [
            "1.  Visita la URL indicada arriba.",
            "2.  Ingresa el código de verificación: {$codeDisplay}",
            "3.  Ingresa el número de documento del firmante: " . $signature['numero_documento'],
            "4.  El sistema confirmará la autenticidad del documento.",
        ];
        foreach ($steps as $step) {
            $pdf->SetX($mL + 4);
            $pdf->MultiCell($cW - 4, 6, $step, 0, 'L');
        }

        $pdf->Ln(4);
        $this->sectionTitle($pdf, 'Datos de Validación');

        $this->dataTable($pdf, [
            'ID del Contrato'    => sprintf('#%06d', $contract['id']),
            'ID de Firma'        => sprintf('#%06d', $signature['id']),
            'Documento Firmante' => $signature['tipo_documento'] . ': ' . $signature['numero_documento'],
            'Fecha de Firma'     => date('d/m/Y H:i:s', strtotime($signature['firmado_at'])),
        ]);
    }

    // =========================================================================
    // MEMBRETE — HEADER y FOOTER (en todas las páginas)
    // =========================================================================

    /**
     * Header completo con membrete: banda azul, logo de texto, nombre empresa,
     * título del documento y numeración de página.
     */
    public function drawHeader(TCPDF $pdf, string $title, array $contract = []): void
    {
        require_once config_path('company-data.php');

        // Usar datos del contrato si existen, sino usar defaults de config
        $companyName = !empty($contract['company_name'])
            ? $contract['company_name']
            : (defined('COMPANY_NAME') ? COMPANY_NAME : 'Sistema de Contratos');

        $companyTagline = defined('COMPANY_TAGLINE') ? COMPANY_TAGLINE : '';

        $companyNit = !empty($contract['company_nit'])
            ? $contract['company_nit']
            : (defined('COMPANY_SHOW_NIT') && COMPANY_SHOW_NIT && defined('COMPANY_NIT') ? COMPANY_NIT : '');

        $hH = $this->headerH; // 22 mm
        $cy = $hH / 2;        // centro vertical = 11 mm

        // ── Banda de fondo ───────────────────────────────────────────────────
        $pdf->SetFillColor(...$this->colorBlue);
        $pdf->Rect(0, 0, $this->pageW, $hH, 'F');

        // ── Línea inferior ───────────────────────────────────────────────────
        $pdf->SetDrawColor(165, 180, 252);
        $pdf->SetLineWidth(0.6);
        $pdf->Line(0, $hH, $this->pageW, $hH);

        // ── Zona IZQUIERDA: logo o círculo + empresa (x: 0–88) ───────────────
        // Verificar si hay logo
        $hasLogo = !empty($contract['logo_path']);
        $logoPath = $hasLogo ? $this->storagePath . '/' . $contract['logo_path'] : '';
        $logoExists = $hasLogo && file_exists($logoPath);

        if ($logoExists) {
            // Mostrar logo
            $logoW = 16;  // ancho máximo del logo
            $logoH = 16;  // alto máximo del logo
            $logoX = 4;   // posición X
            $logoY = ($hH - $logoH) / 2; // centrar verticalmente

            // Fondo blanco para el logo
            $pdf->SetFillColor(255, 255, 255);
            $pdf->RoundedRect($logoX, $logoY, $logoW, $logoH, 2, '1111', 'F');

            // Insertar logo (TCPDF ajustará automáticamente el tamaño)
            $pdf->Image($logoPath, $logoX + 1, $logoY + 1, $logoW - 2, $logoH - 2, '', '', '', false, 300, '', false, false, 0, false, false, false);

            // Nombre empresa al lado del logo
            $pdf->SetFont('dejavusans', 'B', 9);
            $pdf->SetTextColor(255, 255, 255);
            $pdf->SetXY(22, 2.5);
            $pdf->Cell(66, 5.5, $companyName, 0, 0, 'L');
        } else {
            // Círculo con inicial (diseño original)
            $pdf->SetFillColor(255, 255, 255);
            $pdf->SetDrawColor(255, 255, 255);
            $pdf->Circle(12, $cy, 5.5, 0, 360, 'F');
            $pdf->SetFont('helvetica', 'B', 9);
            $pdf->SetTextColor(...$this->colorBlue);
            $pdf->SetXY(6.5, $cy - 4);
            $pdf->Cell(11, 8, mb_strtoupper(mb_substr($companyName, 0, 1)), 0, 0, 'C');

            // Nombre empresa
            $pdf->SetFont('dejavusans', 'B', 9);
            $pdf->SetTextColor(255, 255, 255);
            $pdf->SetXY(21, 2.5);
            $pdf->Cell(66, 5.5, $companyName, 0, 0, 'L');
        }

        // Tagline y/o NIT debajo del nombre
        $subText = '';
        if ($companyTagline) $subText = $companyTagline;
        if ($companyNit)     $subText .= ($subText ? '   ·   NIT: ' : 'NIT: ') . $companyNit;
        if ($subText) {
            $pdf->SetFont('dejavusans', '', 6.5);
            $pdf->SetTextColor(196, 210, 255);
            $pdf->SetXY(21, 10);
            $pdf->Cell(66, 4, $subText, 0, 0, 'L');
        }

        // ── Separadores verticales ───────────────────────────────────────────
        $pdf->SetDrawColor(165, 180, 252);
        $pdf->SetLineWidth(0.35);
        $pdf->Line(90, 3.5, 90, $hH - 3.5);
        $pdf->Line(162, 3.5, 162, $hH - 3.5);

        // ── Zona CENTRAL: título del documento (x: 90–162) ───────────────────
        $pdf->SetFont('dejavusans', 'B', 9.5);
        $pdf->SetTextColor(255, 255, 255);
        $pdf->SetXY(91, $cy - 4);
        $pdf->Cell(70, 8, $title, 0, 0, 'C');

        // ── Zona DERECHA: página + fecha (x: 162–210) ────────────────────────
        $pdf->SetFont('dejavusans', 'B', 9);
        $pdf->SetTextColor(255, 255, 255);
        $pdf->SetXY(163, $cy - 5.5);
        $pdf->Cell(34, 5.5, 'Pág. ' . $pdf->getPage() . ' / ' . $pdf->getAliasNbPages(), 0, 0, 'C');

        $pdf->SetFont('dejavusans', '', 6.5);
        $pdf->SetTextColor(196, 210, 255);
        $pdf->SetXY(163, $cy + 0.5);
        $pdf->Cell(34, 4, date('d/m/Y'), 0, 0, 'C');

        // ── Restablecer ──────────────────────────────────────────────────────
        $pdf->SetY($hH + 6);
        $pdf->SetTextColor(...$this->colorBlack);
        $pdf->SetLineWidth(0.2);
    }

    public function drawFooterStatic(TCPDF $pdf, array $signature, array $contract = []): void
    {
        require_once config_path('company-data.php');

        // Usar datos del contrato si existen, sino usar defaults de config
        $companyName = !empty($contract['company_name'])
            ? $contract['company_name']
            : (defined('COMPANY_NAME') ? COMPANY_NAME : 'Sistema de Contratos');

        $companyEmail = !empty($contract['company_email'])
            ? $contract['company_email']
            : (defined('COMPANY_SHOW_EMAIL') && COMPANY_SHOW_EMAIL && defined('COMPANY_EMAIL') ? COMPANY_EMAIL : '');

        $companyWeb = !empty($contract['company_website'])
            ? $contract['company_website']
            : (defined('COMPANY_SHOW_WEBSITE') && COMPANY_SHOW_WEBSITE && defined('COMPANY_WEBSITE') ? COMPANY_WEBSITE : '');

        $pageH = 297; // A4 mm
        $yF    = $pageH - $this->footerH;

        $pdf->SetDrawColor(...$this->colorBorder);
        $pdf->SetLineWidth(0.3);
        $pdf->Line($this->marginL, $yF, $this->pageW - $this->marginR, $yF);

        $pdf->SetFont('dejavusans', '', 6.5);
        $pdf->SetTextColor(...$this->colorGray);

        // Lado izquierdo: empresa | email | web
        $left = $companyName;
        if ($companyEmail) $left .= '  ·  ' . $companyEmail;
        if ($companyWeb)   $left .= '  ·  ' . $companyWeb;

        $pdf->SetXY($this->marginL, $yF + 2);
        $pdf->Cell(120, 4, $left, 0, 0, 'L');

        // Lado derecho: fecha firma + IP
        $right = 'Firmado: ' . date('d/m/Y H:i', strtotime($signature['firmado_at']))
               . '  ·  IP: ' . $signature['ip_address'];

        $pdf->SetXY($this->pageW - $this->marginR - 60, $yF + 2);
        $pdf->Cell(60, 4, $right, 0, 0, 'R');
    }

    // =========================================================================
    // HELPERS DE DISEÑO
    // =========================================================================

    private function sectionTitle(TCPDF $pdf, string $title): void
    {
        $pdf->SetFont('dejavusans', 'B', 9);
        $pdf->SetTextColor(...$this->colorBlue);
        $pdf->SetFillColor(237, 242, 255);
        $pdf->SetDrawColor(199, 210, 254);
        $pdf->SetLineWidth(0.3);
        $pdf->Cell(0, 7, '  ' . strtoupper($title), 'LB', 1, 'L', true);
        $pdf->Ln(2);
        $pdf->SetTextColor(...$this->colorBlack);
    }

    private function infoBox(TCPDF $pdf, array $rows): void
    {
        $y  = $pdf->GetY();
        $mL = $this->marginL;
        $cW = $this->contentW;

        $rowH = 7;
        $h    = count($rows) * $rowH + 6;

        $pdf->SetFillColor(237, 242, 255);
        $pdf->SetDrawColor(199, 210, 254);
        $pdf->SetLineWidth(0.4);
        $pdf->RoundedRect($mL, $y, $cW, $h, 3, '1111', 'FD');

        $pdf->SetY($y + 3);
        foreach ($rows as $label => $value) {
            $pdf->SetFont('dejavusans', '', 8.5);
            $pdf->SetTextColor(...$this->colorGray);
            $pdf->SetX($mL + 4);
            $pdf->Cell(48, $rowH, $label . ':', 0, 0);
            $pdf->SetFont('dejavusans', 'B', 8.5);
            $pdf->SetTextColor(...$this->colorDark);
            $pdf->Cell(0, $rowH, $value, 0, 1);
        }
        $pdf->Ln(3);
    }

    private function dataTable(TCPDF $pdf, array $rows): void
    {
        $mL  = $this->marginL;
        $cW  = $this->contentW;
        $odd = true;

        foreach ($rows as $label => $value) {
            $pdf->SetFillColor(...($odd ? [248, 250, 252] : [255, 255, 255]));
            $odd = !$odd;

            $pdf->SetFont('dejavusans', '', 9);
            $pdf->SetTextColor(...$this->colorGray);
            $pdf->SetDrawColor(...$this->colorBorder);
            $pdf->SetLineWidth(0.2);
            $pdf->SetX($mL);
            $pdf->Cell(54, 7.5, '  ' . $label, 'B', 0, 'L', true);

            $pdf->SetFont('dejavusans', 'B', 9);
            $pdf->SetTextColor(...$this->colorDark);
            $pdf->MultiCell($cW - 54, 7.5, $value, 'B', 'L', true);
        }
        $pdf->Ln(2);
    }

    private function hashTable(TCPDF $pdf, array $rows): void
    {
        $mL = $this->marginL;
        $cW = $this->contentW;

        foreach ($rows as $label => $hash) {
            // Etiqueta
            $pdf->SetFillColor(...$this->colorDark);
            $pdf->SetTextColor(255, 255, 255);
            $pdf->SetFont('dejavusans', 'B', 7.5);
            $pdf->SetX($mL);
            $pdf->Cell($cW, 5.5, '  ' . $label, 0, 1, 'L', true);

            // Hash
            $pdf->SetFillColor(243, 244, 246);
            $pdf->SetTextColor(...$this->colorBlack);
            $pdf->SetFont('dejavusansmono', '', 7);
            $pdf->SetX($mL);
            $pdf->Cell($cW, 5.5, '  ' . $hash, 0, 1, 'L', true);
            $pdf->Ln(1);
        }
    }

    private function warningBox(TCPDF $pdf, string $msg): void
    {
        $pdf->SetFillColor(254, 242, 242);
        $pdf->SetDrawColor(...$this->colorRed);
        $pdf->SetTextColor(...$this->colorRed);
        $pdf->SetFont('dejavusans', 'I', 8);
        $pdf->SetX($this->marginL);
        $pdf->Cell(0, 8, '⚠  ' . $msg, 1, 1, 'C', true);
        $pdf->Ln(3);
    }

    private function placeholderBox(TCPDF $pdf, float $x, float $y, float $w, float $h, string $label): void
    {
        $pdf->SetDrawColor(...$this->colorBorder);
        $pdf->SetFillColor(243, 244, 246);
        $pdf->Rect($x, $y, $w, $h, 'FD');
        $pdf->SetFont('dejavusans', 'I', 8);
        $pdf->SetTextColor(...$this->colorGray);
        $pdf->SetXY($x, $y + $h / 2 - 3);
        $pdf->Cell($w, 6, $label, 0, 0, 'C');
    }

    private function sanitizeHtmlForPdf(string $html): string
    {
        return strip_tags(
            $html,
            '<p><br><strong><b><em><i><u><h1><h2><h3><ul><ol><li><blockquote><table><tr><td><th><span>'
        );
    }

    // =========================================================================
    // HASHES DE EVIDENCIAS
    // =========================================================================

    private function computeEvidenceHashes(array $signature): array
    {
        $fields = [
            'Firma digital (imagen)'  => $signature['firma_imagen_path']      ?? null,
            'Selfie del firmante'     => $signature['selfie_path']             ?? null,
            'Documento frontal'       => $signature['documento_frontal_path']  ?? null,
            'Documento trasero'       => $signature['documento_trasero_path']  ?? null,
        ];

        $hashes = [];
        foreach ($fields as $label => $relativePath) {
            if ($relativePath === null) {
                $hashes[$label] = '—';
                continue;
            }
            $fullPath       = $this->storagePath . '/' . $relativePath;
            $hashes[$label] = file_exists($fullPath)
                ? hash_file('sha256', $fullPath)
                : '(archivo no encontrado)';
        }

        return $hashes;
    }

    // =========================================================================
    // MÉTODOS PÚBLICOS
    // =========================================================================

    public function getContractPDF(int $signatureId): ?string
    {
        $db        = Database::getInstance();
        $signature = $db->fetchOne(
            "SELECT pdf_path FROM signatures WHERE id = :id",
            [':id' => $signatureId]
        );

        if (!$signature || empty($signature['pdf_path'])) {
            return null;
        }

        $fullPath = $this->storagePath . '/' . $signature['pdf_path'];

        return file_exists($fullPath) ? $fullPath : null;
    }

    public function downloadPDF(string $pdfPath, string $filename = null): void
    {
        $fullPath = file_exists($pdfPath)
            ? $pdfPath
            : $this->storagePath . '/' . ltrim($pdfPath, '/');

        if (!file_exists($fullPath)) {
            throw new \Exception('PDF no encontrado.');
        }

        $filename = $filename ?? basename($fullPath);

        header('Content-Type: application/pdf');
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        header('Content-Length: ' . filesize($fullPath));
        header('Cache-Control: private, max-age=0, must-revalidate');
        header('Pragma: public');

        readfile($fullPath);
        exit;
    }
}
