# Document Sync Debug Protocol

## Overview

This debug protocol provides comprehensive tools for troubleshooting document synchronization failures across three stages:
- **DB → Holded**: Documents sync from database to Holded API (`DocumentSyncService`)
- **Holded → Lawyou**: Status updates and data sync to Lawyou API (`LawyouSyncService`)
- **DB/Holded → Firebase**: Final sync to Firebase (`DocumentSyncService` + `FirebaseSyncService`)

All sync services now include:
- ✅ Trace ID propagation for request tracking
- ✅ Structured error logging to `sync_errors` table
- ✅ Comprehensive error context (document data, stack traces)
- ✅ Integration with HTTP debug API

## Quick Start

### Using HTTP API

```bash
# Diagnose a document
curl "http://localhost/api/debug.php?action=diagnose&type=invoice&id=YOUR_DOC_ID"

# Check prerequisites
curl "http://localhost/api/debug.php?action=prerequisites&type=purchase&id=YOUR_DOC_ID"

# View sync history
curl "http://localhost/api/debug.php?action=history&type=invoice&id=YOUR_DOC_ID"

# Generate full report
curl "http://localhost/api/debug.php?action=report&type=invoice&id=YOUR_DOC_ID"
```

### Using SQL

```sql
-- Check document state
SELECT estado, generarFacturaV, idPedidoVHolded, idFacturaVLawyou
FROM CabeceraFacturasVentas 
WHERE idFacturaVLawyou = 'YOUR_DOC_ID';

-- Check recent errors
SELECT trace_id, sync_stage, error_message, created_at 
FROM sync_errors 
WHERE document_id = 'YOUR_DOC_ID' 
ORDER BY created_at DESC LIMIT 10;

-- Find all errors for a trace
SELECT * FROM sync_errors WHERE trace_id = 'YOUR_TRACE_ID';
```

## Trace ID System

Every sync operation generates a unique trace ID that appears in all related logs and error records.

### Finding Trace IDs

```bash
# From error table
SELECT trace_id FROM sync_errors WHERE document_id = 'YOUR_DOC_ID' LIMIT 1;

# From logs
grep "trace:" /var/log/app.log | tail -n 20
```

### Following a Trace

```bash
# Get all logs for a specific trace
grep "trace:abc123def456" /var/log/app.log

# Get all database errors for a trace
SELECT * FROM sync_errors WHERE trace_id = 'abc123def456';

# Use API to filter by trace
curl "http://localhost/api/debug.php?action=history&type=invoice&id=DOC123&trace_id=abc123def456"
```

## Document States

| Estado | Name | Description |
|--------|------|-------------|
| 0 | Unsynced | Not yet synced to Holded |
| 1 | Pending | Sync in progress |
| 3 | Synced to Holded | Successfully synced to Holded |
| 5 | Synced to Firebase | Successfully synced to Firebase |

## Common Issues & Solutions

### Issue: Document not syncing to Holded

**Symptoms:**
- `estado` remains at 0 or 1
- No Holded ID present

**Debug Steps:**
1. Check if sync flag is enabled: `generarFacturaV=1` or `generarFacturaC=1`
2. Verify user exists and has `holdedId`
3. Check tax information is configured
4. Look for errors in `sync_errors` table with stage `db_to_holded`

**SQL Queries:**
```sql
-- Check document and user
SELECT d.*, u.holdedId, u.ivaVenta, u.irpfVenta
FROM CabeceraFacturasVentas d
JOIN Users u ON d.idContactoLawyou = u.lawyouId
WHERE d.idFacturaVLawyou = 'YOUR_DOC_ID';

-- Check for errors
SELECT * FROM sync_errors 
WHERE document_id = 'YOUR_DOC_ID' 
AND sync_stage = 'db_to_holded'
ORDER BY created_at DESC;
```

### Issue: Document not syncing to Firebase

**Symptoms:**
- `estado` is 3 but not progressing to 5
- Holded ID exists but Firebase sync fails

**Debug Steps:**
1. Verify `estado = 3` (must be synced to Holded first)
2. Check Holded document ID is present
3. Verify Lawyou invoice ID exists
4. Look for Firebase errors in `sync_errors` table

**SQL Queries:**
```sql
-- Check Firebase prerequisites
SELECT estado, idPedidoVHolded, idFacturaVLawyou
FROM CabeceraFacturasVentas 
WHERE idFacturaVLawyou = 'YOUR_DOC_ID';

-- Check Firebase errors
SELECT trace_id, error_message, created_at 
FROM sync_errors 
WHERE document_id = 'YOUR_DOC_ID' 
AND sync_stage = 'to_firebase'
ORDER BY created_at DESC;
```

### Issue: Missing user information

**Error Code:** `MissingUserInfo`

**Solution:**
```sql
-- Find the contact ID
SELECT idContactoLawyou FROM CabeceraFacturasVentas WHERE idFacturaVLawyou = 'YOUR_DOC_ID';

-- Check if user exists
SELECT * FROM Users WHERE lawyouId = 'CONTACT_ID';

-- If missing, user needs to be synced first
```

### Issue: Missing Holded ID

**Error Code:** `MissingHoldedId`

**Solution:**
- Document must be synced to Holded before Firebase sync
- Check if previous Holded sync failed
- Retry Holded sync: `php documentosLawyou.php`

## API Reference

### Diagnose Action

Returns comprehensive diagnostic information about a document.

**Request:**
```
GET /api/debug.php?action=diagnose&type=invoice&id=DOC123
```

**Response:**
```json
{
  "document_id": "DOC123",
  "document_type": "invoice",
  "current_state": {
    "estado": "3",
    "estado_name": "Synced to Holded",
    "holded_id": "holded_abc123",
    "lawyou_id": "DOC123",
    "contact_id": "CONTACT_456"
  },
  "sync_stages": {
    "db_to_holded": {
      "stage_name": "DB → Holded",
      "status": "completed"
    },
    "holded_to_db": {
      "stage_name": "Holded → DB",
      "status": "completed"
    },
    "to_firebase": {
      "stage_name": "DB/Holded → Firebase",
      "status": "pending"
    }
  },
  "missing_prerequisites": [],
  "recent_errors": [],
  "recommended_actions": [
    "Document is ready for Firebase sync",
    "Run Firebase sync script: php documentosLawyou2FBInvoice.php"
  ]
}
```

### Prerequisites Action

Checks all prerequisites for sync operations.

**Request:**
```
GET /api/debug.php?action=prerequisites&type=invoice&id=DOC123
```

**Response:**
```json
{
  "document_id": "DOC123",
  "document_type": "invoice",
  "prerequisites": [
    {
      "name": "User/Contact exists",
      "satisfied": true,
      "value": "CONTACT_456",
      "required_for": "DB → Holded"
    },
    {
      "name": "Contact has Holded ID",
      "satisfied": true,
      "value": "holded_123",
      "required_for": "DB → Holded"
    }
  ]
}
```

### History Action

Returns sync error history for a document.

**Request:**
```
GET /api/debug.php?action=history&type=invoice&id=DOC123&trace_id=abc123
```

**Response:**
```json
{
  "document_id": "DOC123",
  "document_type": "invoice",
  "trace_id": "abc123",
  "total_errors": 2,
  "errors": [
    {
      "id": 1,
      "trace_id": "abc123",
      "sync_stage": "to_firebase",
      "sync_stage_name": "DB/Holded → Firebase",
      "error_code": "FirebaseTimeout",
      "error_message": "Firebase API timeout after 30s",
      "created_at": "2026-03-09 14:30:10"
    }
  ]
}
```

### Report Action

Generates comprehensive debug report with SQL queries.

**Request:**
```
GET /api/debug.php?action=report&type=invoice&id=DOC123
```

**Response:**
```json
{
  "report_generated_at": "2026-03-09 15:00:00",
  "diagnosis": { /* full diagnosis object */ },
  "sync_history": { /* full history object */ },
  "sql_queries": {
    "check_document": "SELECT * FROM CabeceraFacturasVentas WHERE idFacturaVLawyou = 'DOC123';",
    "check_errors": "SELECT * FROM sync_errors WHERE document_id = 'DOC123' AND document_type = 'invoice' ORDER BY created_at DESC LIMIT 10;",
    "check_user": "SELECT u.* FROM Users u JOIN CabeceraFacturasVentas d ON u.lawyouId = d.idContactoLawyou WHERE d.idFacturaVLawyou = 'DOC123';"
  }
}
```

## Error Codes

| Code | Description | Solution |
|------|-------------|----------|
| `MissingUserInfo` | User/contact not found in database | Sync contacts first |
| `MissingHoldedId` | No Holded document ID | Sync to Holded first |
| `MissingDocNumber` | Document number missing from Holded | Check Holded document data |
| `MissingLawyouInvoiceId` | Lawyou invoice ID missing | Check document data integrity |
| `PdfRetrievalFailed` | Failed to retrieve PDF from Holded | Check Holded API and document ID |
| `PdfDecodeFailed` | Failed to decode PDF data | Check PDF data format |
| `HoldedDocumentRetrievalFailed` | Cannot retrieve document from Holded | Check Holded API status |
| `HoldedRetrievalFailed` | Cannot retrieve document from Holded | Check Holded API status |
| `FirebaseSyncFailed` | Firebase sync failed | Check Firebase API and logs |
| `LawyouApiError_XXX` | Lawyou API returned error (XXX = status code) | Check Lawyou API logs and status |

## Maintenance

### Cleanup Old Errors

```sql
-- Delete errors older than 30 days
DELETE FROM sync_errors WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY);
```

Or use the repository method:
```php
$syncErrorRepository->deleteOldErrors(30);
```

### Monitor Error Trends

```sql
-- Errors by stage (last 7 days)
SELECT sync_stage, COUNT(*) as error_count
FROM sync_errors
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)
GROUP BY sync_stage;

-- Most common error codes
SELECT error_code, COUNT(*) as count
FROM sync_errors
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)
GROUP BY error_code
ORDER BY count DESC
LIMIT 10;
```

## Integration with Monitoring

The trace ID system integrates with existing monitoring:
- Trace IDs are automatically included in error reports
- HTTP headers `X-Trace-ID` can be used to set trace context
- All logs include trace ID for correlation

## Support

For issues with the debug protocol itself:
1. Check that `sync_errors` table exists
2. Verify trace logging is working: `grep "trace:" /var/log/app.log`
3. Test API endpoint: `curl http://localhost/api/debug.php?action=diagnose&type=invoice&id=TEST`
