import { NextRequest, NextResponse } from 'next/server'; import { getAutotaskClient } from '@/lib/services/autotask-factory'; import { getDattoRMMClient } from '@/lib/services/datto-rmm-factory'; import { getAuvikClient } from '@/lib/services/auvik-factory'; import { ConfigurationItem } from '@/lib/types/autotask'; import { DattoRMMDevice } from '@/lib/types/datto-rmm'; import { AuvikDevice } from '@/lib/types/auvik'; import { postgresClient } from '@/lib/services/postgres-client'; export async function GET( request: NextRequest, { params }: { params: Promise<{ id: string }> } ) { try { const { id } = await params; const searchParams = request.nextUrl.searchParams; const type = searchParams.get('type') || 'autotask'; let autotaskDevice: ConfigurationItem | null = null; let rmmDevice: DattoRMMDevice | null = null; let auvikDevice: AuvikDevice | null = null; let companyName: string | null = null; if (type === 'autotask') { // Fetch Autotask configuration item const autotaskClient = getAutotaskClient(); autotaskDevice = await autotaskClient.getConfigurationItemById(parseInt(id)); if (autotaskDevice) { // Get company name const company = await autotaskClient.getCompanyById(autotaskDevice.companyID); companyName = company?.companyName || null; // Try to find matching RMM device console.log('Looking for RMM device for Autotask item:', { id: autotaskDevice.id, companyID: autotaskDevice.companyID, companyName: companyName, rmmDeviceUID: autotaskDevice.rmmDeviceUID, rmmDeviceID: autotaskDevice.rmmDeviceID, serialNumber: autotaskDevice.serialNumber, hostname: autotaskDevice.rmmDeviceAuditHostname }); try { const rmmClient = getDattoRMMClient(); const devices = await rmmClient.getAllDevices(); console.log(`Fetched ${devices.length} RMM devices for matching`); // First priority: Match by RMM Device UID if available if (autotaskDevice?.rmmDeviceUID) { rmmDevice = devices.find(d => d.uid === autotaskDevice?.rmmDeviceUID) || null; if (rmmDevice) { console.log('Matched by RMM UID:', rmmDevice.uid); } else { console.log(`No match found for UID: ${autotaskDevice.rmmDeviceUID}`); // Check if device exists with similar UID const similarDevices = devices.filter(d => d.uid && d.uid.includes('3dfd7b06')); console.log(`Devices with similar UID:`, similarDevices.map(d => ({ uid: d.uid, hostname: d.hostname }))); } } // Second priority: Match by serial number if (!rmmDevice && autotaskDevice?.serialNumber) { rmmDevice = devices.find(d => d.serialNumber?.toLowerCase() === autotaskDevice?.serialNumber?.toLowerCase() ) || null; if (rmmDevice) { console.log('Matched by serial number:', rmmDevice.serialNumber); } } // Third priority: Match by hostname if (!rmmDevice && autotaskDevice?.rmmDeviceAuditHostname) { rmmDevice = devices.find(d => d.hostname?.toLowerCase() === autotaskDevice?.rmmDeviceAuditHostname?.toLowerCase() ) || null; if (rmmDevice) console.log('Matched by hostname within company'); } if (!rmmDevice) { console.log('No RMM device match found'); } else { console.log('Found RMM device:', { id: rmmDevice.id, uid: rmmDevice.uid, hostname: rmmDevice.hostname, siteName: rmmDevice.siteName }); // Try to get additional audit data for more detailed information try { const deviceWithAudit = await rmmClient.getDeviceWithAudit(rmmDevice.id); if (deviceWithAudit) { rmmDevice = deviceWithAudit; console.log('Enhanced device with audit data'); } } catch (err) { console.log('Could not fetch audit data:', err); } } } catch (err) { console.error('Failed to fetch RMM device:', err); } // Try to find matching Auvik device using tenant mappings if (autotaskDevice && autotaskDevice.companyID) { try { const auvikClient = getAuvikClient(); // First, check if there's a tenant mapping for this company const mappingQuery = ` SELECT auvik_tenant_id, auvik_tenant_name FROM auvik_tenant_mappings WHERE autotask_company_id = $1 `; const mappingResult = await postgresClient.query<{ auvik_tenant_id: string; auvik_tenant_name: string; }>(mappingQuery, [autotaskDevice.companyID]); let auvikDevices: AuvikDevice[] = []; if (mappingResult.rows.length > 0) { // Use the mapped tenant const mapping = mappingResult.rows[0]; console.log(`Found Auvik tenant mapping: ${mapping.auvik_tenant_name} for company ID: ${autotaskDevice.companyID}`); auvikDevices = await auvikClient.getDevicesByTenant(mapping.auvik_tenant_id); } else if (companyName) { // Fallback to name-based matching console.log(`No mapping found, trying name match for: ${companyName}`); const tenant = await auvikClient.findTenantByName(companyName); if (tenant) { console.log(`Found Auvik tenant by name: ${tenant.domainPrefix} for company: ${companyName}`); auvikDevices = await auvikClient.getDevicesByTenant(tenant.id); } } // Match Auvik device to Autotask configuration item if (auvikDevices.length > 0) { // Priority 1: Match by serial number if (autotaskDevice.serialNumber) { auvikDevice = auvikDevices.find(d => d.serialNumber?.toLowerCase() === autotaskDevice?.serialNumber?.toLowerCase() ) || null; if (auvikDevice) { console.log('Matched Auvik device by serial number:', auvikDevice.serialNumber); } } // Priority 2: Match by hostname if (!auvikDevice && autotaskDevice.rmmDeviceAuditHostname) { auvikDevice = auvikDevices.find(d => d.deviceName?.toLowerCase().includes(autotaskDevice?.rmmDeviceAuditHostname?.toLowerCase() || '') ) || null; if (auvikDevice) { console.log('Matched Auvik device by hostname:', auvikDevice.deviceName); } } // Priority 3: Match by IP address if (!auvikDevice && autotaskDevice.rmmDeviceAuditIPAddress) { auvikDevice = auvikDevices.find(d => d.ipAddresses?.includes(autotaskDevice?.rmmDeviceAuditIPAddress || '') ) || null; if (auvikDevice) { console.log('Matched Auvik device by IP address:', auvikDevice.ipAddresses); } } if (!auvikDevice) { console.log('No Auvik device match found for configuration item'); } } } catch (err) { console.error('Failed to fetch Auvik device:', err); } } } } else if (type === 'rmm') { // Fetch RMM device try { const rmmClient = getDattoRMMClient(); rmmDevice = await rmmClient.getDeviceById(id); if (rmmDevice) { // Try to find matching Autotask device const autotaskClient = getAutotaskClient(); const configItems = await autotaskClient.getAllConfigurationItems(); autotaskDevice = configItems.find(ci => ci.rmmDeviceUID === rmmDevice?.uid || ci.serialNumber === rmmDevice?.serialNumber ) || null; if (autotaskDevice) { const company = await autotaskClient.getCompanyById(autotaskDevice.companyID); companyName = company?.companyName || null; } } } catch (err) { console.error('Failed to fetch RMM device:', err); } } return NextResponse.json({ autotaskDevice, rmmDevice, auvikDevice, companyName }); } catch (error) { console.error('Error fetching configuration item:', error); return NextResponse.json( { error: 'Failed to fetch configuration item details' }, { status: 500 } ); } } export async function PATCH( request: NextRequest, { params }: { params: Promise<{ id: string }> } ) { try { const { id } = await params; const body = await request.json(); const idNum = parseInt(id); const autotaskClient = getAutotaskClient(); const updatedItem = await autotaskClient.updateConfigurationItem(idNum, body); return NextResponse.json({ configurationItem: updatedItem, message: 'Configuration item updated successfully' }); } catch (error) { console.error('Error updating configuration item:', error); return NextResponse.json( { error: 'Failed to update configuration item' }, { status: 500 } ); } }