# Images and Signature Handling

This document explains how the API handles client signatures and vehicle images.

## Overview

The API supports storing binary image data (LONGBLOB) in the database:
- **Client Signature** → `OT.imgfirma`
- **Vehicle VIN Images** → `Vehiculos.img_vin`

Both are optional and use base64 encoding for transmission.

---

## 1. Client Signature (`imgfirma`)

### Purpose
Capture and store the client's signature as proof of service completion or approval.

### Database Field
- **Table**: `OT`
- **Field**: `imgfirma`
- **Type**: `LONGBLOB`
- **Optional**: Yes

### Request Format

```json
{
  "firma": {
    "imgfirma": "data:image/png;base64,iVBORw0KGgo..."
  }
}
```

### Typical Workflow

1. **Frontend Capture**
   - Use HTML5 Canvas or signature pad library
   - Capture signature from mouse/touch input
   
```javascript
// Example: Capture from canvas
const canvas = document.getElementById('signaturePad');
const base64Signature = canvas.toDataURL('image/png');

// Send to API
const payload = {
  // ... other fields ...
  firma: {
    imgfirma: base64Signature
  }
};
```

2. **API Processing**
   - Validates base64 format
   - Strips data URI prefix (`data:image/png;base64,`)
   - Passes clean base64 to stored procedure

3. **Database Storage**
   - Stored procedure converts base64 to binary using `FROM_BASE64()`
   - Stores in `OT.imgfirma` as LONGBLOB

### Validation Rules

- **Format**: Must be valid base64 or data URI
- **Supported image types**: PNG, JPG, JPEG, GIF, WEBP
- **Max size**: 50MB (configurable)
- **Required**: No - can be `null` or omitted

### Example: Complete Request with Signature

```json
{
  "cliente": {
    "rut": "12345678-9",
    "nombre": "Juan Pérez",
    "direccion": "Av. Principal 123",
    "comuna": "Santiago",
    "telefono": "+56912345678",
    "email": "juan@example.com"
  },
  "tecnico": {
    "rut": "98765432-1"
  },
  "servicio": {
    "presGPS": "gpsimple",
    "tiposerv": "instalacion_gps",
    "taller_install": "cartec"
  },
  "firma": {
    "imgfirma": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."
  },
  "vehiculos": [...]
}
```

### Response Indicator

```json
{
  "success": 1,
  "data": {
    "id_ot": 1234,
    "firma_incluida": true  // ← Indicates if signature was stored
  }
}
```

---

## 2. Vehicle VIN Images (`img_vin`)

### Purpose
Store photos of the vehicle's VIN plate for documentation and verification purposes.

### Database Field
- **Table**: `Vehiculos`
- **Field**: `img_vin`
- **Type**: `LONGBLOB`
- **Optional**: Yes

### Request Format

```json
{
  "vehiculos": [
    {
      "patente": "ABCD12",
      "marca": "Toyota",
      "modelo": "Corolla",
      "color": "Blanco",
      "anio": 2020,
      "vin": "1HGBH41JXMN109186",
      "img_vin": "data:image/jpeg;base64,/9j/4AAQSkZJRg..."
    }
  ]
}
```

### Typical Workflow

1. **Frontend Capture**
   - Use device camera or file upload
   - Convert image to base64

```javascript
// Example: Capture from file input
const fileInput = document.getElementById('vinPhoto');
const file = fileInput.files[0];

const reader = new FileReader();
reader.onload = function(e) {
  const base64Image = e.target.result; // Includes data URI
  
  // Add to vehicle object
  vehiculo.img_vin = base64Image;
};
reader.readAsDataURL(file);
```

2. **API Processing**
   - Validates base64 format for each vehicle image
   - Strips data URI prefix
   - Passes clean base64 to stored procedure

3. **Database Storage**
   - Stored procedure converts base64 to binary
   - Stores in `Vehiculos.img_vin` as LONGBLOB
   - If vehicle already exists, updates only if new image provided

### Validation Rules

- **Format**: Must be valid base64 or data URI
- **Supported image types**: PNG, JPG, JPEG, GIF, WEBP
- **Max size**: 50MB per image (configurable)
- **Required**: No - can be `null` or omitted
- **Multiple images**: Each vehicle can have its own image

### Example: Multiple Vehicles with Images

```json
{
  "vehiculos": [
    {
      "patente": "ABCD12",
      "marca": "Toyota",
      "modelo": "Corolla",
      "color": "Blanco",
      "anio": 2020,
      "vin": "1HGBH41JXMN109186",
      "img_vin": "data:image/jpeg;base64,/9j/4AAQSkZJRg..."
    },
    {
      "patente": "WXYZ99",
      "marca": "Chevrolet",
      "modelo": "Cruze",
      "color": "Negro",
      "anio": 2019,
      "vin": "3N1AB7AP1EY123456",
      "img_vin": null  // ← No image for this vehicle
    }
  ]
}
```

### Response Indicator

```json
{
  "success": 1,
  "data": {
    "id_ot": 1234,
    "vehiculos_procesados": 2,
    "vehiculos_con_imagen": 1  // ← Count of vehicles with images
  }
}
```

---

## 3. Base64 Format Handling

### Accepted Formats

Both signature and images accept two base64 formats:

#### 1. With Data URI Prefix (Recommended)
```
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA...
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/...
```

#### 2. Raw Base64
```
iVBORw0KGgoAAAANSUhEUgAAAAUA...
/9j/4AAQSkZJRgABAQAAAQABAAD/...
```

### API Processing

The `cleanBase64()` function automatically:
- Detects data URI prefix
- Strips prefix if present
- Returns clean base64 for database storage

```javascript
// Internal API function
const cleanBase64 = img => {
    if (!img) return null;
    return img.replace(/^data:image\/[a-z]+;base64,/, '');
};
```

### Validation

The `validateBase64Image()` function checks:
- Valid data URI format OR raw base64 format
- Supported image types (png, jpg, jpeg, gif, webp)

```javascript
const validateBase64Image = img => {
    if (!img || typeof img !== 'string') return false;
    const base64Regex = /^data:image\/(png|jpg|jpeg|gif|webp);base64,/;
    return base64Regex.test(img) || /^[A-Za-z0-9+/=]+$/.test(img);
};
```

---

## 4. Database Operations

### Stored Procedure: `prc_api_create_OT`

#### Signature Processing

```sql
DECLARE v_imgfirma LONGBLOB DEFAULT NULL;

-- Convert base64 to binary
IF p_imgfirma_base64 IS NOT NULL AND LENGTH(p_imgfirma_base64) > 0 THEN
    SET v_imgfirma = FROM_BASE64(p_imgfirma_base64);
END IF;

-- Store in OT table
INSERT INTO OT (..., imgfirma, ...) 
VALUES (..., v_imgfirma, ...);
```

#### Vehicle Image Processing

```sql
DECLARE v_img_vin LONGBLOB;

-- Extract from JSON and convert
SET v_img_vin_base64 = JSON_UNQUOTE(JSON_EXTRACT(v_vehiculo_json, '$.img_vin'));

IF v_img_vin_base64 IS NOT NULL AND LENGTH(v_img_vin_base64) > 0 THEN
    SET v_img_vin = FROM_BASE64(v_img_vin_base64);
ELSE
    SET v_img_vin = NULL;
END IF;

-- Insert or update vehicle
INSERT INTO Vehiculos (..., img_vin, ...) 
VALUES (..., v_img_vin, ...)
ON DUPLICATE KEY UPDATE 
  img_vin = COALESCE(v_img_vin, img_vin);  -- Keep existing if new is null
```

---

## 5. Retrieval and Display

### Querying Images from Database

```sql
-- Get signature
SELECT imgfirma FROM OT WHERE id_ot = 1234;

-- Get vehicle image
SELECT img_vin FROM Vehiculos WHERE patente = 'ABCD12';
```

### Converting Back to Base64 for Display

```sql
-- Return as base64
SELECT 
  id_ot,
  TO_BASE64(imgfirma) as firma_base64
FROM OT 
WHERE id_ot = 1234;
```

### Frontend Display

```javascript
// Received from API
const firmaBase64 = response.firma_base64;

// Display in img tag
const imgElement = document.createElement('img');
imgElement.src = `data:image/png;base64,${firmaBase64}`;
document.body.appendChild(imgElement);
```

---

## 6. Best Practices

### Signature Capture
- Use PNG format for signatures (better for line art)
- Recommended canvas size: 400x200 to 600x300 pixels
- Use transparent background for signatures
- Compress if size > 100KB

### VIN Photos
- Use JPEG format for photos (better compression)
- Recommended max resolution: 1920x1080
- Good lighting and focus on VIN plate
- Compress to < 500KB per image

### Performance
- Upload images only when necessary
- Consider thumbnail generation for previews
- Implement client-side compression
- Use lazy loading for image display

### Security
- Validate file sizes before upload
- Check MIME types
- Sanitize filenames if storing externally
- Implement rate limiting for image uploads

---

## 7. Testing

### Test Signature Upload

```bash
# Generate small test signature
echo "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==" > test_sig.b64

curl -X POST http://localhost:3000/api/ot/create \
  -H "Content-Type: application/json" \
  -d '{
    "cliente": {...},
    "tecnico": {...},
    "servicio": {...},
    "firma": {
      "imgfirma": "data:image/png;base64,'$(cat test_sig.b64)'"
    },
    "vehiculos": [...]
  }'
```

### Verify in Database

```sql
-- Check if signature was stored
SELECT 
  id_ot,
  CASE 
    WHEN imgfirma IS NULL THEN 'No signature'
    ELSE CONCAT('Signature size: ', LENGTH(imgfirma), ' bytes')
  END as signature_status
FROM OT
WHERE id_ot = 1234;
```

---

## 8. Troubleshooting

### Error: "Imagen de firma debe ser base64 válida"

**Cause**: Invalid base64 format or unsupported image type

**Solution**: 
- Check data URI prefix: `data:image/png;base64,`
- Ensure supported format (png, jpg, jpeg, gif, webp)
- Verify base64 encoding is correct

### Error: "Error SQL: 22032"

**Cause**: Invalid base64 data sent to `FROM_BASE64()` function

**Solution**:
- Ensure base64 is properly cleaned (no whitespace, line breaks)
- Check for corrupted base64 strings
- Validate encoding before sending

### Large Image Upload Fails

**Cause**: Image exceeds configured size limit

**Solution**:
- Increase limit in `src/index.js`: `app.use(express.json({ limit: '50mb' }))`
- Compress images client-side before upload
- Use JPEG instead of PNG for photos

### Image Not Displaying

**Cause**: Incorrect MIME type or corrupted data

**Solution**:
- Query with `TO_BASE64()` to verify storage
- Check data URI prefix when displaying
- Verify image isn't corrupted during encoding/decoding

---

## Summary

| Feature | Field | Table | Format | Required | Max Size |
|---------|-------|-------|--------|----------|----------|
| Client Signature | `imgfirma` | `OT` | Base64 PNG | No | 50MB |
| Vehicle VIN Image | `img_vin` | `Vehiculos` | Base64 JPG/PNG | No | 50MB |

Both features use the same base64 encoding/decoding pipeline and are fully optional. The API handles format detection, validation, and conversion automatically.

