# Admin Seat Details Endpoint - Complete Specification

## Overview

This document specifies a comprehensive admin-only endpoint for retrieving detailed information about individual seats, including ownership, reservation status, pricing, and historical data.

**Endpoint**: `GET /api/admin/seats/{seat_id}/details`

**Authentication**: Admin JWT required (`auth.admin.jwt` middleware)

**Rate Limiting**: `api.rate.limit:admin`

**Purpose**: Provide complete seat context for admin tooltips, seat management operations, and troubleshooting

---

## Current Gap

The existing `/api/venue/availability/{eventId}` endpoint only returns:
- Seat status (available/held/booked)
- Seat price
- Basic seat identifiers

**Missing critical admin data**:
- Owner information (customer name, email)
- Order details (order ID, payment status)
- Hold/reservation timing information
- Pricing history and snapshots
- Admin operation history
- Payment and transaction context

---

## Endpoint Specification

### Request

```
GET /api/admin/seats/{seat_id}/details?event_id={event_id}
```

**Path Parameters**:
- `seat_id` (required) - UUID of the seat (e.g., `seat-A1-12345`)

**Query Parameters**:
- `event_id` (optional but recommended) - Event ID for event-specific context
- `include_history` (optional, boolean) - Include reservation history (default: false)
- `include_audit_logs` (optional, boolean) - Include audit trail (default: false)

---

## Response Structure

### Success Response (200 OK)

```json
{
  "success": true,
  "data": {
    "seat": {
      "seat_id": "seat-A1-12345",
      "event_id": 42,
      "row_letter": "A",
      "seat_number": "1",
      "display_name": "A1",
      "seat_type": "individual",
      "zone": "VIP",
      "section_id": "section-vip-001",
      "is_accessible": false,
      "is_active": true,
      "price": 150.00,
      "position": {
        "x": 100,
        "y": 200,
        "rotation": 0
      },
      "parent_table_id": null,
      "created_at": "2025-10-15T10:00:00Z",
      "updated_at": "2025-10-20T14:30:00Z"
    },

    "event": {
      "id": 42,
      "name": "Concert - Beyoncé",
      "slug": "concert-beyonce",
      "start_date": "2025-12-15T20:00:00Z",
      "venue_id": 5,
      "venue_name": "Madison Square Garden",
      "status": "active"
    },

    "reservation": {
      "id": 1234,
      "status": "booked",
      "status_label": "Booked",
      "created_at": "2025-10-20T15:30:00Z",
      "updated_at": "2025-10-20T15:32:00Z",

      "hold_details": {
        "hold_token": "abc123def456",
        "session_id": "sess_xyz789",
        "expires_at": null,
        "seconds_remaining": null,
        "held_at": "2025-10-20T15:30:00Z",
        "hold_duration_seconds": 120
      },

      "pricing": {
        "price_snapshot": 150.00,
        "current_seat_price": 150.00,
        "price_changed": false,
        "snapshot_taken_at": "2025-10-20T15:30:00Z"
      },

      "owner": {
        "type": "customer",
        "customer_name": "John Doe",
        "customer_email": "john.doe@example.com",
        "customer_phone": "+1234567890",
        "user_id": null,
        "is_guest": true
      },

      "order": {
        "order_id": 5678,
        "session_id": "sess_xyz789",
        "total_amount": 183.25,
        "status": "completed",
        "status_label": "Completed",
        "payment_status": "paid",
        "payment_method": "stripe",
        "payment_mode": "immediate",
        "idempotency_key": "idem_abc123",
        "created_at": "2025-10-20T15:32:00Z",
        "updated_at": "2025-10-20T15:32:00Z"
      },

      "payment": {
        "payment_transaction_id": 9012,
        "payment_gateway": "stripe",
        "transaction_id": "pi_1J2K3L4M5N6O7P8Q",
        "amount": 183.25,
        "currency": "EUR",
        "status": "completed",
        "initiated_at": "2025-10-20T15:31:00Z",
        "completed_at": "2025-10-20T15:32:00Z",
        "stripe_customer_id": "cus_ABC123",
        "metadata": {
          "payment_mode": "immediate",
          "seat_count": 1
        }
      },

      "admin_context": {
        "is_shadow_sold": false,
        "is_blocked": false,
        "is_comp": false,
        "created_by_admin": false,
        "created_by_admin_id": null,
        "admin_notes": null
      }
    },

    "line_items": [
      {
        "id": 101,
        "order_id": 5678,
        "item_type": "ticket",
        "description": "Ticket: Seat A1",
        "quantity": 1,
        "unit_price": 150.00,
        "line_total": 150.00,
        "tax_rate": 0,
        "tax_amount": 0,
        "seat_id": "seat-A1-12345"
      },
      {
        "id": 102,
        "order_id": 5678,
        "item_type": "booking_fee",
        "description": "Service Fee",
        "quantity": 1,
        "unit_price": 3.75,
        "line_total": 3.75,
        "tax_rate": 0,
        "tax_amount": 0,
        "seat_id": null
      },
      {
        "id": 103,
        "order_id": 5678,
        "item_type": "tax",
        "description": "VAT (21%)",
        "quantity": 1,
        "unit_price": 32.29,
        "line_total": 32.29,
        "tax_rate": 0.21,
        "tax_amount": 32.29,
        "seat_id": null
      }
    ],

    "availability": {
      "is_available": false,
      "is_held": false,
      "is_booked": true,
      "is_shadow_sold": false,
      "is_blocked": false,
      "can_be_released": false,
      "can_be_reassigned": true,
      "can_be_refunded": true
    },

    "history": [
      {
        "id": 4001,
        "status": "held",
        "created_at": "2025-10-20T15:30:00Z",
        "expires_at": "2025-10-20T15:40:00Z",
        "hold_token": "abc123def456",
        "session_id": "sess_xyz789"
      },
      {
        "id": 4001,
        "status": "booked",
        "created_at": "2025-10-20T15:32:00Z",
        "expires_at": null,
        "order_id": 5678
      }
    ],

    "audit_logs": [
      {
        "id": 9001,
        "action_type": "seat_hold",
        "action_category": "seat_management",
        "action_description": "Seat held by customer",
        "performed_by_type": "customer",
        "performed_by_id": null,
        "performed_by_name": "john.doe@example.com",
        "performed_at": "2025-10-20T15:30:00Z",
        "metadata": {
          "session_id": "sess_xyz789",
          "hold_token": "abc123def456"
        }
      },
      {
        "id": 9002,
        "action_type": "seat_booking_confirmed",
        "action_category": "seat_management",
        "action_description": "Booking confirmed after payment",
        "performed_by_type": "system",
        "performed_by_id": null,
        "performed_by_name": "Payment Webhook",
        "performed_at": "2025-10-20T15:32:00Z",
        "metadata": {
          "order_id": 5678,
          "payment_intent": "pi_1J2K3L4M5N6O7P8Q"
        }
      }
    ],

    "related_seats": {
      "parent_table": null,
      "child_seats": [],
      "section_seats_total": 50,
      "section_seats_available": 12,
      "section_seats_held": 3,
      "section_seats_booked": 35
    }
  }
}
```

---

## Data Sources & Relationships

### Primary Tables

1. **`seats`** - Base seat information
   - `seat_id`, `event_id`, `row_letter`, `seat_number`, `price`, `zone`
   - `section_id`, `seat_type`, `is_accessible`, `is_active`
   - `position`, `parent_table_id`, `parametric`, `child_seats`

2. **`seat_reservations`** - Current reservation status
   - `id`, `event_id`, `seat_id`, `status`
   - `hold_token`, `session_id`, `user_id`
   - `expires_at`, `price_snapshot`
   - `created_at`, `updated_at`
   - Status values: `held`, `booked`, `shadow_sold`, `blocked`

3. **`orders`** - Order details (if seat is booked)
   - `id`, `event_id`, `session_id`, `user_id`
   - `customer_name`, `customer_email`, `customer_phone`
   - `total_amount`, `status`, `payment_status`, `payment_method`, `payment_mode`
   - `idempotency_key`, `created_by_admin_id`, `admin_notes`

4. **`order_line_items`** - Detailed pricing breakdown
   - `id`, `order_id`, `item_type`, `description`
   - `quantity`, `unit_price`, `line_total`
   - `tax_rate`, `tax_amount`, `seat_id`
   - Item types: `ticket`, `booking_fee`, `tax`, `discount`

5. **`payment_transactions`** - Payment details
   - `id`, `order_id`, `payment_gateway`, `transaction_id`
   - `amount`, `currency`, `status`
   - `initiated_at`, `completed_at`, `metadata`

6. **`events`** - Event context
   - `id`, `name`, `slug`, `start_date`, `venue_id`, `status`

7. **`mbs_activity_logs`** (optional) - Admin operation audit trail
   - `id`, `action_type`, `action_category`, `action_description`
   - `performed_by_type`, `performed_by_id`, `performed_by_name`
   - `event_id`, `seat_id`, `seat_identifier`
   - `performed_at`, `metadata`

---

## Business Logic & Calculations

### Availability Status Determination

```php
// Based on seat_reservations table
if (no reservation exists) {
    is_available = true
} else if (status === 'held' AND expires_at > NOW) {
    is_held = true
} else if (status === 'booked') {
    is_booked = true
} else if (status === 'shadow_sold') {
    is_shadow_sold = true
} else if (status === 'blocked') {
    is_blocked = true
}
```

### Admin Actions Availability

```php
can_be_released = (is_held OR is_booked) AND NOT is_shadow_sold
can_be_reassigned = is_booked AND order.can_be_modified
can_be_refunded = is_booked AND order.status IN ['completed', 'paid']
```

### Hold Duration Calculation

```php
if (status === 'held' AND expires_at !== null) {
    hold_duration_seconds = expires_at - created_at
    seconds_remaining = expires_at - NOW (can be negative if expired)
}
```

### Price Change Detection

```php
price_changed = (seat.price !== reservation.price_snapshot)
```

---

## Use Cases

### 1. Admin Tooltip on Seat Hover
**Frontend needs**: Basic seat info + owner + status
**Response**: All fields in `seat`, `reservation.owner`, `reservation.status`

### 2. Seat Operations Panel
**Frontend needs**: Full context for refunds, reassignments, releases
**Response**: Full `reservation`, `order`, `payment`, `availability`

### 3. Customer Support Investigation
**Frontend needs**: Complete history and audit trail
**Response**: Full response with `include_history=true` and `include_audit_logs=true`

### 4. Fire Marshal Report
**Frontend needs**: Section capacity and occupied seat details
**Response**: `seat`, `related_seats` section statistics

### 5. Pricing Audit
**Frontend needs**: Price snapshot vs current price
**Response**: `reservation.pricing`, `line_items`

---

## Error Responses

### 404 Not Found
```json
{
  "success": false,
  "message": "Seat not found",
  "errors": {
    "seat_id": "No seat exists with ID: seat-A1-12345"
  }
}
```

### 403 Forbidden
```json
{
  "success": false,
  "message": "Admin authentication required",
  "errors": {
    "auth": "This endpoint requires admin privileges"
  }
}
```

### 422 Validation Error
```json
{
  "success": false,
  "message": "Invalid seat ID format",
  "errors": {
    "seat_id": "Seat ID must be a valid UUID or seat identifier"
  }
}
```

---

## Performance Considerations

### Query Optimization

1. **Use Eager Loading** to prevent N+1 queries:
   ```php
   $seat = Seat::with([
       'event',
       'reservations' => function($query) {
           $query->latest()->with(['order.lineItems', 'order.paymentTransactions']);
       }
   ])->find($seatId);
   ```

2. **Conditional Loading** for expensive queries:
   - Only load `history` if `include_history=true`
   - Only load `audit_logs` if `include_audit_logs=true`

3. **Index Requirements**:
   - `seat_reservations.seat_id` (already indexed)
   - `seat_reservations.event_id` (already indexed)
   - `order_line_items.seat_id` (should be indexed)
   - `mbs_activity_logs.seat_id` (should be indexed)

### Caching Strategy

- **Cache duration**: 10 seconds (seat status changes frequently)
- **Cache key**: `admin_seat_details:{seat_id}:{event_id}`
- **Cache invalidation**: On seat status change, order creation/update, admin action

---

## Implementation Checklist

### Backend Implementation (Laravel)

- [ ] Create `AdminSeatDetailsController.php`
- [ ] Add route to `/routes/api/admin/seats.php` or create new file
- [ ] Implement query with eager loading
- [ ] Add validation for seat_id and event_id
- [ ] Implement conditional loading for history and audit logs
- [ ] Add response formatting with proper JSON structure
- [ ] Add logging for admin access (GDPR audit trail)
- [ ] Add rate limiting specific to this endpoint (optional)
- [ ] Add tests (unit + integration)

### Frontend Integration (Next.js)

- [ ] Create TypeScript interface for response structure
- [ ] Add API client method in admin API service
- [ ] Update seat tooltip component to call new endpoint
- [ ] Add loading states and error handling
- [ ] Implement caching strategy (React Query or similar)
- [ ] Add seat operations panel with admin actions
- [ ] Test with various seat states (available, held, booked, etc.)

---

## Security & Compliance

### Authentication
- **Required**: Admin JWT token
- **Middleware**: `auth.admin.jwt`
- **Validation**: Verify admin user has appropriate permissions

### Authorization
- **Permission**: `seats.view_details` (optional granular permission)
- **Scope**: All seats within admin's accessible events

### Audit Logging
Log every access to this endpoint for GDPR compliance:
```php
\Log::info('ADMIN_SEAT_DETAILS_ACCESS', [
    'admin_id' => auth('admin')->id(),
    'seat_id' => $seatId,
    'event_id' => $eventId,
    'ip_address' => request()->ip(),
    'user_agent' => request()->userAgent(),
    'timestamp' => now()->toISOString(),
]);
```

### Data Privacy
- **Customer Data**: Only accessible to authenticated admins
- **PII Protection**: Customer email/phone only visible to admins with `customers.view_pii` permission (optional)
- **Anonymization**: Respect `orders.is_anonymized` flag

---

## Additional Recommendations

### Future Enhancements

1. **Real-time Updates**: WebSocket or SSE for live seat status changes
2. **Bulk Seat Details**: Endpoint to fetch details for multiple seats at once
3. **Historical Pricing**: Track price changes over time for analytics
4. **Customer Account Link**: Direct link to customer account page (if exists)
5. **Ticket PDF Preview**: Link to download ticket PDF from seat details
6. **Refund Calculator**: Calculate potential refund amount based on order line items
7. **Similar Seats**: Suggest similar available seats for customer service

### Error Monitoring

- **Sentry/Bugsnag**: Track endpoint errors and response times
- **Performance Monitoring**: Alert if response time > 500ms
- **Missing Data Alerts**: Log warnings if expected related data is missing

### Documentation

- **API Documentation**: Add to OpenAPI/Swagger spec
- **Admin Guide**: Document seat management workflows
- **Troubleshooting Guide**: Common issues and solutions

---

## Summary

This endpoint provides a **complete admin view of any seat** in the system, including:

✅ **Basic seat data** (location, type, price)
✅ **Current reservation status** (available, held, booked)
✅ **Owner information** (customer name, email, order ID)
✅ **Pricing context** (snapshot vs current, line items)
✅ **Payment details** (transaction, gateway, status)
✅ **Admin context** (shadow sold, comp, admin notes)
✅ **Historical data** (status changes over time)
✅ **Audit trail** (admin actions, system events)
✅ **Related data** (parent table, section statistics)

This comprehensive endpoint will **eliminate the need for multiple API calls** and provide admins with all the context they need for effective seat management, customer support, and troubleshooting.
