# Delete Visit (Cancel) Endpoint Guide

## Overview

The **Delete Visit** endpoint performs a **soft delete** by changing the visit status to "Canceled". It does NOT physically remove the record from the database, ensuring data integrity and audit trail preservation.

## Endpoint Details

**URL**: `DELETE /api/visits/{id}`

**Authentication**: Required (Bearer token)

**Authorization**: `admin` role OR the host who created the visit

## Request

### URL Parameters
- `id` (integer, required) - The visit ID to cancel

### No Request Body Required
This is a DELETE request with no body needed.

## Response

### Success Response (200 OK)
```json
{
  "message": "Visit canceled successfully",
  "status": "Canceled"
}
```

### Error Responses

#### 403 Forbidden (Not Authorized)
```json
{
  "message": "Forbidden"
}
```
User is not the host and doesn't have admin role.

#### 404 Not Found
```json
{
  "message": "Visit not found"
}
```
Visit with the specified ID doesn't exist.

#### 422 Validation Error (Cannot Cancel)
```json
{
  "message": "Cannot cancel visit. Only visits with status Pending Visitor, Pending Approve, Pending Host, or Approved can be canceled.",
  "current_status": "Completed"
}
```
Visit is in a final state that cannot be canceled.

## Status Validation Rules

### ✅ Can Cancel These Statuses:
- **Pending Visitor** - Before visitor registration
- **Pending Approve** - After visitor registration, awaiting security approval
- **Pending Host** - Returned to host for corrections
- **Approved** - Approved but not yet completed

### ❌ Cannot Cancel These Statuses:
- **Completed** - Visit already finished
- **Rejected** - Visit already rejected by security
- **Expired** - Registration token already expired
- **Canceled** - Already canceled

## Status Flow

```
Pending Visitor ──┐
Pending Approve ──┤
Pending Host ─────┤──► [DELETE] ──► Canceled
Approved ─────────┘

Completed ────┐
Rejected ─────┤──► [DELETE] ──► ❌ Error 422
Expired ──────┤
Canceled ─────┘
```

## Authorization Rules

### Who Can Delete a Visit?

1. **Admin Users**: Can cancel ANY visit (regardless of host)
   - admin@beyti.test

2. **Host Users**: Can only cancel their OWN visits
   - Must be the user who created the visit
   - `visit.host_email` must match authenticated user's email

3. **Security Users**: CANNOT delete visits
   - Can only approve/reject/return

## Implementation Details

### Model Method: `canBeDeleted()`
Location: `app/Models/Visit.php:172`

```php
public function canBeDeleted(): bool
{
    return !in_array($this->status, ['Completed', 'Rejected', 'Expired', 'Canceled']);
}
```

### Controller Method: `destroy()`
Location: `app/Http/Controllers/Api/VisitController.php:235`

```php
public function destroy(Request $request, int $id)
{
    $visit = Visit::findOrFail($id);

    // Get user info
    $userEmail = $request->user();
    $userRole = UserRole::where('email', $userEmail)->first();

    // Authorization check - only admin or the host can delete
    if (!$userRole->hasRole(['admin']) && $visit->host_email !== $userEmail) {
        return response()->json(['message' => 'Forbidden'], 403);
    }

    // Check if visit can be deleted
    if (!$visit->canBeDeleted()) {
        return response()->json([
            'message' => 'Cannot cancel visit. Only visits with status Pending Visitor, Pending Approve, Pending Host, or Approved can be canceled.',
            'current_status' => $visit->status,
        ], 422);
    }

    // Soft delete by setting status to Canceled
    $this->statusService->transition(
        $visit,
        'Canceled',
        'Visit canceled by ' . ($userRole->hasRole(['admin']) ? 'admin' : 'host'),
        $userEmail,
        $userRole->name ?? null
    );

    return response()->json([
        'message' => 'Visit canceled successfully',
        'status' => 'Canceled',
    ]);
}
```

### Route
Location: `routes/api.php:77`

```php
Route::delete('/{id}', [VisitController::class, 'destroy']);
```

## Database Changes

When a visit is canceled, the following database updates occur:

1. **visits table**:
   - `status` → "Canceled"
   - `updated_at` → Current timestamp

2. **visit_status_history table** (new record):
   - `visit_id` → Visit ID
   - `from_status` → Previous status (e.g., "Pending Visitor")
   - `to_status` → "Canceled"
   - `changed_by_email` → User email who canceled
   - `changed_by_name` → User name who canceled
   - `reason` → "Visit canceled by admin" or "Visit canceled by host"
   - `created_at` → Current timestamp

## Testing with Postman

1. **Import Collection**: Use the updated `Beyti-API.postman_collection.json`

2. **Generate Token**:
   - Go to "Test Authentication" folder
   - Run "Generate Test Token" with appropriate user:
     ```json
     {
       "email": "host@beyti.test"
     }
     ```
     or
     ```json
     {
       "email": "admin@beyti.test"
     }
     ```

3. **Test Delete Endpoint**:
   - Navigate to: **Visits → Delete Visit (Cancel)**
   - Update visit ID in URL (e.g., `:id` = `3`)
   - Click "Send"

4. **Verify Result**:
   - Check response status is "Canceled"
   - Verify visit still exists in database with status "Canceled"
   - Check status history shows the transition

## Testing with cURL

### As Host (Own Visit)
```bash
curl -X DELETE "http://localhost:8080/beyti-api/public/api/visits/3" \
  -H "Authorization: Bearer YOUR_HOST_TOKEN"
```

### As Admin (Any Visit)
```bash
curl -X DELETE "http://localhost:8080/beyti-api/public/api/visits/3" \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"
```

## Use Cases

### Use Case 1: Host Cancels Before Visitor Registration
**Scenario**: Host needs to cancel meeting before visitor registers

**Status**: Pending Visitor → Canceled

**Action**:
```bash
DELETE /api/visits/3
Authorization: Bearer {host_token}
```

**Result**: Visit canceled, visitor registration link no longer valid

### Use Case 2: Host Cancels After Security Approval
**Scenario**: Meeting canceled due to host unavailability

**Status**: Approved → Canceled

**Action**:
```bash
DELETE /api/visits/1
Authorization: Bearer {host_token}
```

**Result**: Visit canceled, notifications sent (if configured)

### Use Case 3: Admin Cancels Any Visit
**Scenario**: Admin needs to cancel visit for any reason

**Status**: Any allowed status → Canceled

**Action**:
```bash
DELETE /api/visits/8
Authorization: Bearer {admin_token}
```

**Result**: Visit canceled with admin attribution

### Use Case 4: Cannot Cancel Completed Visit
**Scenario**: Attempting to cancel a completed visit

**Status**: Completed

**Action**:
```bash
DELETE /api/visits/5
```

**Result**: Error 422 - Cannot cancel completed visit

## Comparison: Delete vs Reject

| Feature | Delete (Cancel) | Reject |
|---------|----------------|--------|
| **Who Can Do It** | Host or Admin | Security only |
| **Status Change** | → Canceled | → Rejected |
| **Allowed From** | Pending*, Approved | Pending Approve |
| **Use When** | Host initiated cancellation | Security denies visit |
| **Requires Reason** | No (auto-generated) | Yes (required) |
| **Can Resubmit** | Must create new visit | Must create new visit |

## Best Practices

### When to Use Delete

✅ **Use Delete when:**
- Host cannot host the meeting
- Visitor is no longer coming
- Meeting rescheduled (create new visit)
- Duplicate visit request
- Host made a mistake in the request

❌ **Don't Use Delete when:**
- Visit is completed (use completion workflow)
- Security concerns (use Reject)
- Visit already rejected/expired/canceled

### Authorization Best Practices

1. **Host Users**: Can only cancel their own pending/approved visits
2. **Admin Users**: Can cancel any visit for administrative purposes
3. **Security Users**: Should use Reject instead for security-related denials

## Troubleshooting

### Issue: "Forbidden" Error
**Cause**: User is not the host and not an admin
**Solution**:
- Generate token with correct host user OR admin user
- Verify the visit's `host_email` matches the authenticated user

### Issue: "Cannot cancel visit..." Error (422)
**Cause**: Visit is in final state (Completed, Rejected, Expired, or Canceled)
**Solution**:
- Check current visit status using GET /api/visits/{id}
- Final states cannot be canceled - this is expected behavior

### Issue: "Visit not found" Error (404)
**Cause**: Invalid visit ID
**Solution**: Verify visit ID exists using GET /api/visits endpoint

## Testing Scenarios

### Scenario 1: Cancel Pending Visitor Visit
```bash
# Create visit
POST /api/visits
{
  "hostVisitor": {...},
  "mainVisitorEmail": "test@example.com",
  ...
}

# Cancel it immediately (before visitor registers)
DELETE /api/visits/21

# Verify status is Canceled
GET /api/visits/21
# Response: { "status": "Canceled", ... }
```

### Scenario 2: Try to Cancel Completed Visit
```bash
# Try to cancel a completed visit (ID 4 in test data)
DELETE /api/visits/4

# Expected Error Response (422):
{
  "message": "Cannot cancel visit. Only visits with status Pending Visitor, Pending Approve, Pending Host, or Approved can be canceled.",
  "current_status": "Completed"
}
```

### Scenario 3: Host vs Admin Authorization
```bash
# Host tries to cancel another host's visit
DELETE /api/visits/1
Authorization: Bearer {host_token_for_different_user}
# Result: 403 Forbidden

# Admin cancels the same visit
DELETE /api/visits/1
Authorization: Bearer {admin_token}
# Result: 200 OK, visit canceled
```

## Verification Queries

### Check Visit Status After Deletion
```sql
SELECT id, request_id, status, host_email
FROM visits
WHERE id = 3;
-- Should show status = 'Canceled'
```

### Check Status History
```sql
SELECT visit_id, from_status, to_status, changed_by_email, reason, created_at
FROM visit_status_history
WHERE visit_id = 3
ORDER BY created_at DESC;
-- Should show transition to 'Canceled'
```

### Count Canceled Visits
```sql
SELECT COUNT(*) as canceled_count
FROM visits
WHERE status = 'Canceled';
```

## Related Endpoints

- **Create Visit**: `POST /api/visits`
- **Update Visit**: `PUT /api/visits/{id}`
- **Get Visit**: `GET /api/visits/{id}`
- **Reject Visit**: `POST /api/visits/{id}/reject` (Security)
- **Return Visit**: `POST /api/visits/{id}/return` (Security)
- **Approve Visit**: `POST /api/visits/{id}/approve` (Security)

## Workflow Integration

```
[Host creates visit]
        ↓
  Pending Visitor ───────┐
        ↓                │ [Host cancels]
 [Visitor registers]     │
        ↓                │
  Pending Approve ───────┤
        ↓                │ [Host/Admin cancels]
[Security approves]      │
        ↓                │
     Approved ───────────┤
        ↓                ↓
    Completed        Canceled
```

## Important Notes

1. **Soft Delete Only**: Visits are NEVER physically deleted from the database
2. **Audit Trail**: All status changes are recorded in visit_status_history
3. **Cannot Undo**: Once canceled, the visit cannot be "un-canceled"
4. **Must Create New**: If meeting is rescheduled, create a new visit request
5. **No Email**: Currently no email notification sent on cancellation (can be added)
