# Tasks: Auvik Integration

## Relevant Files

- `/lib/types/auvik.ts` - TypeScript type definitions for Auvik API entities (devices, tenants, interfaces)
- `/lib/services/auvik-client.ts` - Auvik API client service for making authenticated requests
- `/lib/services/auvik-factory.ts` - Singleton factory pattern for Auvik client instantiation
- `/app/api/auvik/devices/route.ts` - API endpoint for fetching Auvik devices with tenant filtering
- `/components/configuration-items/auvik-tab.tsx` - React component for displaying Auvik device details in modal
- `/components/configuration-items/config-item-modal.tsx` - Existing modal component (modify to add Auvik tab)
- `/app/configuration-items/page.tsx` - Main configuration items page (modify to add Auvik column)
- `/app/api/configuration-items/[id]/route.ts` - Existing API route (modify to include Auvik device matching)
- `/app/api/rmm-devices/route.ts` - Existing comparison endpoint (modify to include Auvik matching)

### Notes

- Follow existing patterns from Datto RMM integration (`datto-rmm-client.ts`, `rmm-tab.tsx`)
- Use Basic Authentication for Auvik API (username:password in Authorization header)
- Auvik API documentation: https://support.auvik.com/hc/en-us/articles/360031007111
- Test with real Auvik credentials from `.env` file
- Ensure graceful degradation when Auvik API is unavailable

## Tasks

- [ ] 1.0 Create Auvik TypeScript Types and API Client
  - [ ] 1.1 Create `/lib/types/auvik.ts` with TypeScript interfaces for AuvikDevice, AuvikTenant, AuvikNetworkInterface, and API response structures
  - [ ] 1.2 Define AuvikDevice interface with fields: id, deviceName, serialNumber, macAddresses, ipAddresses, deviceType, manufacturer, model, firmwareVersion, onlineStatus, lastSeenTime, uptime, tenantId, tenantName
  - [ ] 1.3 Define AuvikNetworkInterface interface with fields: interfaceName, status, speed, macAddress, ipAddress, vlan
  - [ ] 1.4 Create `/lib/services/auvik-client.ts` implementing AuvikClient class with constructor accepting config (apiUrl, apiUser, apiKey)
  - [ ] 1.5 Implement `getAuthHeaders()` method that returns Basic Authentication header (Base64 encoded username:password)
  - [ ] 1.6 Implement `makeApiCall<T>()` method for generic API requests with error handling and logging
  - [ ] 1.7 Implement `getAllDevices()` method to fetch device inventory from `/v1/inventory/device/info` endpoint
  - [ ] 1.8 Implement `getDevicesByTenant(tenantId: string)` method with tenant filtering
  - [ ] 1.9 Implement `getTenants()` method to fetch tenant list from `/v1/tenants` endpoint
  - [ ] 1.10 Add rate limiting logic to respect Auvik API limits (track request count and timestamps)
  - [ ] 1.11 Create `/lib/services/auvik-factory.ts` with `getAuvikClient()` singleton factory function
  - [ ] 1.12 Load Auvik credentials from environment variables in factory (AUVIK_API_URL, AUVIK_API_USER, AUVIK_API_KEY)

- [ ] 2.0 Implement Auvik API Endpoints
  - [ ] 2.1 Create `/app/api/auvik/devices/route.ts` with GET handler
  - [ ] 2.2 Accept query parameters: `companyId` (optional), `companyName` (optional)
  - [ ] 2.3 If companyName provided, fetch Auvik tenants and find matching tenant by name (case-insensitive, fuzzy match)
  - [ ] 2.4 If tenant match found, fetch devices filtered by tenantId; otherwise fetch all devices
  - [ ] 2.5 Transform Auvik API response to match AuvikDevice interface structure
  - [ ] 2.6 Implement try-catch error handling that logs errors but returns 200 with empty array on failure
  - [ ] 2.7 Add console logging for tenant matching results and device counts
  - [ ] 2.8 Return JSON response with devices array and optional metadata (tenantId, tenantName)

- [ ] 3.0 Add Auvik Tab to Configuration Item Modal
  - [ ] 3.1 Create `/components/configuration-items/auvik-tab.tsx` component accepting `device?: AuvikDevice` prop
  - [ ] 3.2 Import required UI components (Card, CardContent, CardHeader, Badge, Label) and icons (Network, Info, Wifi, Shield)
  - [ ] 3.3 Implement empty state UI when no device provided (show "No Auvik data available" message with icon)
  - [ ] 3.4 Create "Basic Information" section displaying: device name, device type, serial number, manufacturer, model
  - [ ] 3.5 Create "Network Information" section displaying: IP addresses (list), MAC addresses (list), primary interface details
  - [ ] 3.6 Create "Status Information" section displaying: online/offline badge, last seen timestamp (formatted), uptime (formatted duration)
  - [ ] 3.7 Create "Firmware Information" section displaying: firmware version, last updated date
  - [ ] 3.8 Create "Network Interfaces" section displaying table/list of interfaces with name, status, speed, MAC address
  - [ ] 3.9 Style online status with green badge and Wifi icon, offline with gray badge and X icon
  - [ ] 3.10 Use consistent spacing and layout matching existing PSA/RMM tabs (2-column grid on desktop)
  - [ ] 3.11 Modify `/components/configuration-items/config-item-modal.tsx` to add Auvik tab to TabsList
  - [ ] 3.12 Add TabsTrigger for "Auvik Data" with Network icon and online/offline badge if device exists
  - [ ] 3.13 Add TabsContent for "auvik" value rendering AuvikTab component with auvikDevice prop
  - [ ] 3.14 Update modal state to include `auvikDevice?: AuvikDevice` in ConfigItemDetail interface

- [ ] 4.0 Add Auvik Column to Configuration Items Table
  - [ ] 4.1 Open `/app/configuration-items/page.tsx` and locate the table header row (TableHead components)
  - [ ] 4.2 Add new `<TableHead>Auvik</TableHead>` column after the RMM column
  - [ ] 4.3 Update colspan values in grouped rows from current value to +1 (account for new column)
  - [ ] 4.4 In the table body, add new TableCell after RMM cell for grouped rows
  - [ ] 4.5 Display green CheckCircle icon if `item.auvikDevice` exists, gray XCircle if not
  - [ ] 4.6 Add same TableCell logic for non-grouped rows (around line 1060+)
  - [ ] 4.7 Update DeviceComparison interface to include `auvikDevice?: AuvikDevice` field
  - [ ] 4.8 Import AuvikDevice type from `/lib/types/auvik`

- [ ] 5.0 Implement Device Matching Logic
  - [ ] 5.1 Modify `/app/api/rmm-devices/route.ts` to fetch Auvik devices at the start of GET handler
  - [ ] 5.2 Call `getAuvikClient().getAllDevices()` or `getDevicesByTenant()` if companyName provided
  - [ ] 5.3 Wrap Auvik API call in try-catch to handle failures gracefully (continue with empty array)
  - [ ] 5.4 Create helper function `matchAuvikDevice(autotaskDevice: ConfigurationItem, auvikDevices: AuvikDevice[]): AuvikDevice | null`
  - [ ] 5.5 Implement Priority 1 matching: Compare serial numbers (case-insensitive, trimmed)
  - [ ] 5.6 Implement Priority 2 matching: Compare hostnames using `rmmDeviceAuditHostname` or `referenceTitle` (case-insensitive)
  - [ ] 5.7 Implement Priority 3 matching: Compare MAC addresses (normalize format, check against all device MACs)
  - [ ] 5.8 Create `normalizeMacAddress()` helper function to strip colons/hyphens and lowercase
  - [ ] 5.9 In comparison loop, call matchAuvikDevice for each autotaskDevice and add result to comparison object
  - [ ] 5.10 Log matching results with match method (serial/hostname/MAC) for debugging
  - [ ] 5.11 Modify `/app/api/configuration-items/[id]/route.ts` GET handler to fetch Auvik devices
  - [ ] 5.12 Use same matchAuvikDevice logic to find matching device for the single configuration item
  - [ ] 5.13 Include auvikDevice in response JSON: `{ autotaskDevice, rmmDevice, auvikDevice, companyName }`
  - [ ] 5.14 Add console logging for Auvik device matching in detail endpoint

- [ ] 6.0 Testing and Error Handling
  - [ ] 6.1 Test Auvik API authentication with valid credentials (verify 200 response)
  - [ ] 6.2 Test with invalid credentials (verify graceful failure, no app crash)
  - [ ] 6.3 Test device matching with serial number match (verify correct device returned)
  - [ ] 6.4 Test device matching with hostname match (verify fallback works)
  - [ ] 6.5 Test device matching with MAC address match (verify normalization works)
  - [ ] 6.6 Test device matching with no match (verify null returned, "-" displayed)
  - [ ] 6.7 Test with company that has no Auvik tenant (verify all devices returned or empty array)
  - [ ] 6.8 Test tenant name matching with exact match and fuzzy match scenarios
  - [ ] 6.9 Test configuration items page with Auvik API unavailable (verify page still loads)
  - [ ] 6.10 Test modal opening with Auvik device (verify tab displays data correctly)
  - [ ] 6.11 Test modal opening without Auvik device (verify empty state message)
  - [ ] 6.12 Test table column alignment with new Auvik column (verify no layout issues)
  - [ ] 6.13 Verify console logs show appropriate messages for matching, errors, and API calls
  - [ ] 6.14 Test with large device list (100+ devices) to verify performance
  - [ ] 6.15 Test responsive layout on mobile/tablet (verify Auvik tab and column display correctly)
  - [ ] 6.16 Verify TypeScript compilation with no errors
  - [ ] 6.17 Test that existing PSA and RMM functionality is not affected by changes
