import { requireSalesOrAdmin } from '~/server/utils/auth'; import { getNocoDbConfiguration } from '~/server/utils/nocodb'; import { logAuditEvent } from '~/server/utils/audit-logger'; import { findDuplicates, createInterestConfig } from '~/server/utils/duplicate-detection'; export default defineEventHandler(async (event) => { console.log('[INTERESTS] Find duplicates request'); try { // Require sales or admin access for duplicate detection await requireSalesOrAdmin(event); const query = getQuery(event); const threshold = query.threshold ? parseFloat(query.threshold as string) : 0.8; const dateRange = query.dateRange ? parseInt(query.dateRange as string) : 365; // Default 1 year // Get all interests from NocoDB const config = getNocoDbConfiguration(); const interestTableId = "mbs9hjauug4eseo"; // Interest table ID let url = `${config.url}/api/v2/tables/${interestTableId}/records`; // Add date filtering if specified (include records without Created At) if (dateRange && dateRange > 0) { const cutoffDate = new Date(); cutoffDate.setDate(cutoffDate.getDate() - dateRange); // Include records without Created At OR within date range const dateFilter = `((Created At,gte,${cutoffDate.toISOString()}),or,(Created At,is,null))`; url += `?where=${encodeURIComponent(dateFilter)}`; } const response = await $fetch(url, { headers: { 'xc-token': config.token }, params: { limit: 5000 // Get a large batch for duplicate detection } }) as any; const interests = response.list || []; console.log('[INTERESTS] Analyzing', interests.length, 'interests for duplicates'); // Find duplicate groups using the new centralized utility const duplicateConfig = createInterestConfig(); const duplicateGroups = findDuplicates(interests, duplicateConfig); // Convert to the expected format const formattedGroups = duplicateGroups.map(group => ({ id: group.id, interests: group.items, matchReason: group.matchReason, confidence: group.confidence, masterCandidate: group.masterCandidate })); console.log('[INTERESTS] Found', formattedGroups.length, 'duplicate groups'); // Log the audit event await logAuditEvent(event, 'FIND_INTEREST_DUPLICATES', 'interest', { changes: { totalInterests: interests.length, duplicateGroups: formattedGroups.length, threshold, dateRange } }); return { success: true, data: { duplicateGroups: formattedGroups, totalInterests: interests.length, duplicateCount: formattedGroups.reduce((sum, group) => sum + group.interests.length, 0), threshold, dateRange } }; } catch (error: any) { console.error('[INTERESTS] Failed to find duplicates:', error); if (error.statusCode === 403) { return { success: false, error: 'Insufficient permissions. Sales or admin access required.' }; } return { success: false, error: 'Failed to find duplicates' }; } });