import { NextRequest, NextResponse } from 'next/server'; import { Pool } from 'pg'; import { getAuvikClient } from '@/lib/services/auvik-factory'; import { AuvikTenantMapping } from '@/lib/types/auvik'; const pool = new Pool({ host: process.env.POSTGRES_HOST, port: parseInt(process.env.POSTGRES_PORT || '5432'), database: process.env.POSTGRES_DB, user: process.env.POSTGRES_USER, password: process.env.POSTGRES_PASSWORD, }); export async function GET(request: NextRequest) { try { const searchParams = request.nextUrl.searchParams; const includeUnmapped = searchParams.get('includeUnmapped') === 'true'; // Get all mappings from database const result = await pool.query<{ id: number; auvik_tenant_id: string; auvik_tenant_name: string; autotask_company_id: number; autotask_company_name: string; created_at: string; updated_at: string; }>('SELECT * FROM auvik_tenant_mappings ORDER BY auvik_tenant_name'); const mappings: AuvikTenantMapping[] = result.rows.map((row) => ({ id: row.id, auvikTenantId: row.auvik_tenant_id, auvikTenantName: row.auvik_tenant_name, autotaskCompanyId: row.autotask_company_id, autotaskCompanyName: row.autotask_company_name, createdAt: row.created_at, updatedAt: row.updated_at, })); // If includeUnmapped is true, fetch all Auvik tenants and merge if (includeUnmapped) { const auvikClient = getAuvikClient(); const allTenants = await auvikClient.getTenants(); const mappedTenantIds = new Set(mappings.map((m) => m.auvikTenantId)); const unmappedTenants = allTenants .filter((t) => !mappedTenantIds.has(t.id)) .map((t) => ({ id: 0, // Temporary ID for unmapped auvikTenantId: t.id, auvikTenantName: t.domainPrefix, autotaskCompanyId: 0, autotaskCompanyName: '', createdAt: '', updatedAt: '', })); return NextResponse.json({ mappings: [...mappings, ...unmappedTenants], totalMapped: mappings.length, totalUnmapped: unmappedTenants.length, }); } return NextResponse.json({ mappings }); } catch (error) { console.error('Error fetching tenant mappings:', error); return NextResponse.json( { error: 'Failed to fetch tenant mappings' }, { status: 500 } ); } } export async function POST(request: NextRequest) { try { const body = await request.json(); const { auvikTenantId, auvikTenantName, autotaskCompanyId, autotaskCompanyName, } = body; if (!auvikTenantId || !autotaskCompanyId) { return NextResponse.json( { error: 'Missing required fields' }, { status: 400 } ); } // Insert or update mapping const result = await pool.query<{ id: number; auvik_tenant_id: string; auvik_tenant_name: string; autotask_company_id: number; autotask_company_name: string; created_at: string; updated_at: string; }>( `INSERT INTO auvik_tenant_mappings (auvik_tenant_id, auvik_tenant_name, autotask_company_id, autotask_company_name) VALUES ($1, $2, $3, $4) ON CONFLICT (auvik_tenant_id) DO UPDATE SET autotask_company_id = EXCLUDED.autotask_company_id, autotask_company_name = EXCLUDED.autotask_company_name, updated_at = CURRENT_TIMESTAMP RETURNING *`, [auvikTenantId, auvikTenantName, autotaskCompanyId, autotaskCompanyName] ); const mapping: AuvikTenantMapping = { id: result.rows[0].id, auvikTenantId: result.rows[0].auvik_tenant_id, auvikTenantName: result.rows[0].auvik_tenant_name, autotaskCompanyId: result.rows[0].autotask_company_id, autotaskCompanyName: result.rows[0].autotask_company_name, createdAt: result.rows[0].created_at, updatedAt: result.rows[0].updated_at, }; return NextResponse.json({ mapping }); } catch (error) { console.error('Error creating tenant mapping:', error); return NextResponse.json( { error: 'Failed to create tenant mapping' }, { status: 500 } ); } } export async function DELETE(request: NextRequest) { try { const searchParams = request.nextUrl.searchParams; const id = searchParams.get('id'); if (!id) { return NextResponse.json( { error: 'Missing mapping ID' }, { status: 400 } ); } await pool.query('DELETE FROM auvik_tenant_mappings WHERE id = $1', [ parseInt(id), ]); return NextResponse.json({ success: true }); } catch (error) { console.error('Error deleting tenant mapping:', error); return NextResponse.json( { error: 'Failed to delete tenant mapping' }, { status: 500 } ); } }