← back to Norma

app/api/email-analyzer/references/route.ts

186 lines

/**
 * GET    /api/email-analyzer/references?session_id=xxx — list references for a session
 * POST   /api/email-analyzer/references — add a reference
 * DELETE  /api/email-analyzer/references?id=xxx — remove a reference
 */

import { NextRequest, NextResponse } from 'next/server';
import { query } from '@/lib/db';
import { requireRole } from '@/lib/require-role';

export async function GET(request: NextRequest) {
  const auth = requireRole(request, 'admin', 'staff');
  if (auth instanceof NextResponse) return auth;

  try {
    const { searchParams } = new URL(request.url);
    const sessionId = searchParams.get('session_id');

    if (!sessionId) {
      return NextResponse.json({ error: 'session_id is required' }, { status: 400 });
    }

    const result = await query(
      `SELECT * FROM email_analyzer_references
       WHERE session_id = $1
       ORDER BY sort_order ASC, created_at ASC`,
      [sessionId],
    );

    return NextResponse.json({ references: result.rows });
  } catch (err) {
    console.error('[email-analyzer/references] GET error:', (err as Error).message);
    return NextResponse.json({ error: 'Failed to fetch references' }, { status: 500 });
  }
}

export async function POST(request: NextRequest) {
  const auth = requireRole(request, 'admin', 'staff');
  if (auth instanceof NextResponse) return auth;

  try {
    const body = await request.json();
    const {
      session_id,
      ref_type,
      title,
      source_url,
      source_domain,
      content,
      key_points,
      include_in_rewrite,
      sort_order,
    } = body;

    if (!session_id || typeof session_id !== 'string') {
      return NextResponse.json({ error: 'session_id is required' }, { status: 400 });
    }

    if (!ref_type || !['article', 'link', 'notes'].includes(ref_type)) {
      return NextResponse.json(
        { error: 'ref_type must be one of: article, link, notes' },
        { status: 400 },
      );
    }

    if (!content || typeof content !== 'string') {
      return NextResponse.json({ error: 'content is required' }, { status: 400 });
    }

    // Get next sort_order if not provided
    let finalSortOrder = sort_order;
    if (finalSortOrder == null) {
      const maxResult = await query(
        `SELECT COALESCE(MAX(sort_order), -1) + 1 AS next_order
         FROM email_analyzer_references
         WHERE session_id = $1`,
        [session_id],
      );
      finalSortOrder = maxResult.rows[0]?.next_order ?? 0;
    }

    const result = await query(
      `INSERT INTO email_analyzer_references
         (session_id, ref_type, title, source_url, source_domain, content, key_points, include_in_rewrite, sort_order)
       VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
       RETURNING *`,
      [
        session_id,
        ref_type,
        title || null,
        source_url || null,
        source_domain || null,
        content,
        JSON.stringify(key_points || []),
        include_in_rewrite !== false,
        finalSortOrder,
      ],
    );

    return NextResponse.json({ reference: result.rows[0] }, { status: 201 });
  } catch (err) {
    console.error('[email-analyzer/references] POST error:', (err as Error).message);
    return NextResponse.json({ error: 'Failed to save reference' }, { status: 500 });
  }
}

export async function DELETE(request: NextRequest) {
  const auth = requireRole(request, 'admin', 'staff');
  if (auth instanceof NextResponse) return auth;

  try {
    const { searchParams } = new URL(request.url);
    const id = searchParams.get('id');

    if (!id) {
      return NextResponse.json({ error: 'id is required' }, { status: 400 });
    }

    const result = await query(
      `DELETE FROM email_analyzer_references WHERE id = $1 RETURNING id`,
      [id],
    );

    if (result.rowCount === 0) {
      return NextResponse.json({ error: 'Reference not found' }, { status: 404 });
    }

    return NextResponse.json({ deleted: true, id });
  } catch (err) {
    console.error('[email-analyzer/references] DELETE error:', (err as Error).message);
    return NextResponse.json({ error: 'Failed to delete reference' }, { status: 500 });
  }
}

export async function PATCH(request: NextRequest) {
  const auth = requireRole(request, 'admin', 'staff');
  if (auth instanceof NextResponse) return auth;

  try {
    const body = await request.json();
    const { id, include_in_rewrite, sort_order } = body;

    if (!id) {
      return NextResponse.json({ error: 'id is required' }, { status: 400 });
    }

    const updates: string[] = [];
    const values: unknown[] = [];
    let paramIdx = 1;

    if (include_in_rewrite !== undefined) {
      updates.push(`include_in_rewrite = $${paramIdx}`);
      values.push(include_in_rewrite);
      paramIdx++;
    }

    if (sort_order !== undefined) {
      updates.push(`sort_order = $${paramIdx}`);
      values.push(sort_order);
      paramIdx++;
    }

    if (updates.length === 0) {
      return NextResponse.json({ error: 'No fields to update' }, { status: 400 });
    }

    values.push(id);
    const result = await query(
      `UPDATE email_analyzer_references
       SET ${updates.join(', ')}
       WHERE id = $${paramIdx}
       RETURNING *`,
      values,
    );

    if (result.rowCount === 0) {
      return NextResponse.json({ error: 'Reference not found' }, { status: 404 });
    }

    return NextResponse.json({ reference: result.rows[0] });
  } catch (err) {
    console.error('[email-analyzer/references] PATCH error:', (err as Error).message);
    return NextResponse.json({ error: 'Failed to update reference' }, { status: 500 });
  }
}