# Servicio de Rellenado de Formularios PDF

Este servicio permite rellenar formularios PDF con campos editables (AcroForms) y generar archivos PDF descargables.

## 📋 Requisitos

### Dependencias PHP (Ya instaladas)
- `setasign/fpdi` - Para manipulación de PDFs
- `mikehaertl/php-pdftk` - Para rellenar formularios PDF

### PDFtk Server (Requerido en el servidor)

**Windows:**
1. Descargar desde: https://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/
2. Instalar PDFtk Server
3. Agregar a la variable PATH del sistema

**Linux:**
```bash
sudo apt-get install pdftk
```

**Mac:**
```bash
brew install pdftk-java
```

## 🚀 Uso Básico

### 1. Uso directo del servicio

```php
use App\Services\PdfFormFillerService;

$pdfService = new PdfFormFillerService();

$result = $pdfService->fillPdfForm(
    'plantillas/contrato.pdf',  // Ruta de la plantilla
    [
        'nombre_cliente' => 'Juan Pérez',
        'dni' => '12345678A',
        'fecha' => '2024-10-22',
        'direccion' => 'Calle Principal 123'
    ]
);

if ($result['success']) {
    echo "PDF generado: " . $result['url'];
    // URL: http://tu-dominio.com/storage/pdfs/generated/abc-123-def.pdf
}
```

### 2. Uso con Trait en Controllers

```php
use App\Traits\PdfFormFillable;

class ContratoController extends Controller
{
    use PdfFormFillable;

    public function generarContrato(Request $request)
    {
        $data = [
            'nombre_cliente' => $request->nombre,
            'dni' => $request->dni,
            'cups' => $request->cups,
            'tarifa' => $request->tarifa
        ];

        // Opción 1: Retornar JSON con la URL
        return $this->fillAndReturnPdf('plantillas/contrato.pdf', $data);

        // Opción 2: Descargar directamente
        return $this->fillAndDownloadPdf(
            'plantillas/contrato.pdf', 
            $data,
            'contrato-' . $request->dni . '.pdf'
        );

        // Opción 3: Mostrar en el navegador
        return $this->fillAndShowPdf('plantillas/contrato.pdf', $data);
    }
}
```

## 📁 Estructura de Carpetas

```
storage/
  app/
    public/
      pdfs/
        templates/          # Aquí van las plantillas PDF
          contrato.pdf
          factura.pdf
        generated/          # Aquí se guardan los PDFs generados
          abc-123-def.pdf
```

## 🔧 Configuración Avanzada

### Cambiar carpetas de salida

```php
$pdfService = new PdfFormFillerService();

$pdfService
    ->setOutputFolder('contratos/2024')
    ->setTemplatesFolder('pdfs/plantillas')
    ->fillPdfForm('contrato.pdf', $data);
```

### Usar disco diferente

```php
$pdfService = new PdfFormFillerService('local');
// O usando el método
$pdfService->setDisk('s3');
```

### Nombre personalizado con UUID

```php
$result = $pdfService->fillPdfForm(
    'plantillas/contrato.pdf',
    $data,
    'contrato-cliente-12345'  // Nombre personalizado
);
// Genera: contrato-cliente-12345.pdf
```

## 📝 Métodos Disponibles

### PdfFormFillerService

#### `fillPdfForm(string $templatePath, array $data, ?string $customFilename = null, bool $flatten = true)`
Rellena un formulario PDF con los datos proporcionados.

**Parámetros:**
- `$templatePath`: Ruta del PDF plantilla
- `$data`: Array asociativo [nombre_campo => valor]
- `$customFilename`: Nombre personalizado (opcional, sin extensión)
- `$flatten`: Si es true, los campos no serán editables en el PDF final

**Retorna:**
```php
[
    'success' => true,
    'path' => 'pdfs/generated/abc-123.pdf',
    'url' => 'http://example.com/storage/pdfs/generated/abc-123.pdf',
    'filename' => 'abc-123.pdf',
    'message' => 'PDF generado exitosamente'
]
```

#### `getPdfFields(string $templatePath)`
Obtiene la lista de campos disponibles en un PDF.

```php
$fields = $pdfService->getPdfFields('plantillas/contrato.pdf');
// ['nombre_cliente', 'dni', 'fecha', 'direccion']
```

#### `deletePdf(string $path)`
Elimina un PDF generado.

```php
$pdfService->deletePdf('pdfs/generated/abc-123.pdf');
```

#### `checkPdftkAvailability()`
Verifica si PDFtk está instalado.

```php
$status = $pdfService->checkPdftkAvailability();
```

### Trait PdfFormFillable

#### `fillAndReturnPdf()` 
Genera el PDF y retorna JSON con la URL.

#### `fillAndDownloadPdf()` 
Genera el PDF y lo descarga directamente.

#### `fillAndShowPdf()` 
Genera el PDF y lo muestra inline en el navegador.

#### `getPdfFormFields()` 
Obtiene los campos del formulario.

#### `deletePdfFile()` 
Elimina un archivo PDF.

## 🎯 Ejemplos de Uso

### Ejemplo 1: Generar contrato y retornar URL

```php
public function generarContrato(Request $request)
{
    $data = [
        'nombre' => $request->cliente->nombre,
        'dni' => $request->cliente->dni,
        'cups' => $request->punto_suministro->cups,
        'tarifa' => $request->tarifa->nombre,
        'fecha_inicio' => now()->format('d/m/Y'),
        'precio_kwh' => $request->tarifa->precio
    ];

    $result = app(PdfFormFillerService::class)->fillPdfForm(
        'plantillas/contrato_luz.pdf',
        $data,
        'contrato-' . $request->cliente->id
    );

    if ($result['success']) {
        // Guardar la URL en la base de datos
        $contrato = Contrato::create([
            'cliente_id' => $request->cliente->id,
            'pdf_path' => $result['path'],
            'pdf_url' => $result['url']
        ]);

        return response()->json([
            'message' => 'Contrato generado',
            'contrato_id' => $contrato->id,
            'download_url' => $result['url']
        ]);
    }

    return response()->json(['error' => $result['message']], 500);
}
```

### Ejemplo 2: Descargar PDF directamente

```php
use App\Traits\PdfFormFillable;

class ContratoController extends Controller
{
    use PdfFormFillable;

    public function descargarContrato($id)
    {
        $contrato = Contrato::with('cliente', 'puntoSuministro')->findOrFail($id);

        $data = [
            'nombre' => $contrato->cliente->nombre,
            'dni' => $contrato->cliente->dni,
            'cups' => $contrato->puntoSuministro->cups,
            'tarifa' => $contrato->tarifa->nombre
        ];

        return $this->fillAndDownloadPdf(
            'plantillas/contrato.pdf',
            $data,
            'contrato-' . $contrato->id . '.pdf'
        );
    }
}
```

### Ejemplo 3: Obtener campos de un PDF

```php
public function obtenerCamposPdf()
{
    $pdfService = new PdfFormFillerService();
    $fields = $pdfService->getPdfFields('plantillas/contrato.pdf');

    if ($fields['success']) {
        return response()->json([
            'campos_disponibles' => $fields['fields']
        ]);
    }

    return response()->json(['error' => $fields['message']], 500);
}
```

## 🔐 Rutas API (Ejemplo)

Puedes agregar estas rutas a tu archivo `routes/api.php`:

```php
use App\Http\Controllers\PdfFormController;

Route::prefix('pdf')->group(function () {
    Route::post('/fill', [PdfFormController::class, 'fillForm']);
    Route::post('/download', [PdfFormController::class, 'downloadForm']);
    Route::post('/view', [PdfFormController::class, 'viewForm']);
    Route::get('/fields', [PdfFormController::class, 'getFields']);
    Route::delete('/delete', [PdfFormController::class, 'deleteFile']);
    Route::get('/status', [PdfFormController::class, 'checkStatus']);
});
```

## 📤 Ejemplos de Request

### Rellenar formulario

```bash
POST http://localhost/api/pdf/fill
Content-Type: application/json

{
  "template": "plantillas/contrato.pdf",
  "data": {
    "nombre_cliente": "Juan Pérez",
    "dni": "12345678A",
    "fecha": "2024-10-22",
    "cups": "ES0021000000000001JN",
    "tarifa": "2.0TD"
  },
  "filename": "contrato-juan-perez",
  "flatten": true
}
```

**Respuesta:**
```json
{
  "success": true,
  "path": "pdfs/generated/contrato-juan-perez.pdf",
  "url": "http://localhost/storage/pdfs/generated/contrato-juan-perez.pdf",
  "filename": "contrato-juan-perez.pdf",
  "message": "PDF generado exitosamente"
}
```

### Obtener campos disponibles

```bash
GET http://localhost/api/pdf/fields?template=plantillas/contrato.pdf
```

**Respuesta:**
```json
{
  "success": true,
  "fields": [
    "nombre_cliente",
    "dni",
    "fecha",
    "cups",
    "tarifa",
    "direccion"
  ],
  "message": "Campos obtenidos exitosamente"
}
```

## 🛠️ Crear un PDF con campos rellenables

Para crear un PDF con campos editables, puedes usar:

1. **Adobe Acrobat Pro** - Herramientas > Preparar formulario
2. **LibreOffice Draw** - Insertar campos de formulario y exportar como PDF
3. **PDF-XChange Editor** - Alternativa gratuita con campos de formulario

**Nombres de campos importantes:**
- Los nombres de campos no deben tener espacios (usar guiones bajos)
- Distinguen entre mayúsculas y minúsculas
- Ejemplo: `nombre_cliente`, `DNI`, `fecha_contrato`

## ⚠️ Notas Importantes

1. **PDFtk debe estar instalado** en el servidor para que funcione
2. Los PDFs deben tener campos de formulario (AcroForms)
3. El enlace simbólico de storage debe estar creado: `php artisan storage:link`
4. Los archivos generados se guardan en `storage/app/public/pdfs/generated/`
5. Las URLs son públicas y accesibles directamente

## 🔍 Debugging

### Verificar si PDFtk está instalado

```php
$pdfService = new PdfFormFillerService();
$status = $pdfService->checkPdftkAvailability();
dd($status);
```

### Ver campos disponibles en un PDF

```php
$fields = $pdfService->getPdfFields('plantillas/contrato.pdf');
dd($fields);
```

## 📞 Soporte

Si tienes problemas:
1. Verifica que PDFtk esté instalado: `pdftk --version`
2. Verifica que el storage link esté creado: `php artisan storage:link`
3. Revisa los permisos de la carpeta storage: `chmod -R 775 storage`
4. Verifica que el PDF tenga campos de formulario editables

