← back to Norma

app/api/email-analyzer/subject-lines/route.ts

116 lines

/**
 * Subject Line Maker + history.
 *
 *   POST   /api/email-analyzer/subject-lines/generate — AI: generate N subject options
 *   GET    /api/email-analyzer/subject-lines?session_id=xxx — list saved subjects
 *   POST   /api/email-analyzer/subject-lines — save a subject the user picked
 *   PATCH  /api/email-analyzer/subject-lines — update favorite / notes
 *   DELETE /api/email-analyzer/subject-lines?id=xxx — remove
 */

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 sessionId = new URL(request.url).searchParams.get('session_id');
    const where = sessionId ? 'WHERE session_id = $1' : '';
    const params = sessionId ? [sessionId] : [];
    const { rows } = await query(
      `SELECT id, session_id, version_id, subject, style, reasoning,
              is_favorite, notes, created_at
         FROM email_analyzer_subject_lines
         ${where}
         ORDER BY is_favorite DESC, created_at DESC
         LIMIT 200`,
      params,
    );
    return NextResponse.json({ subjects: rows });
  } catch (err) {
    console.error('[subject-lines] GET error:', (err as Error).message);
    return NextResponse.json({ error: 'Failed to load subjects' }, { 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, version_id, subject, style, reasoning, notes } = body;
    if (!session_id || !subject) {
      return NextResponse.json({ error: 'session_id and subject are required' }, { status: 400 });
    }
    const { rows } = await query(
      `INSERT INTO email_analyzer_subject_lines
         (session_id, version_id, subject, style, reasoning, notes)
       VALUES ($1, $2, $3, $4, $5, $6)
       RETURNING *`,
      [session_id, version_id || null, subject, style || null, reasoning || null, notes || null],
    );
    return NextResponse.json({ subject: rows[0] }, { status: 201 });
  } catch (err) {
    console.error('[subject-lines] POST error:', (err as Error).message);
    return NextResponse.json({ error: 'Failed to save subject' }, { status: 500 });
  }
}

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

  try {
    const { id, is_favorite, notes } = await request.json();
    if (!id) return NextResponse.json({ error: 'id required' }, { status: 400 });

    const sets: string[] = [];
    const params: unknown[] = [];
    if (is_favorite !== undefined) {
      params.push(is_favorite);
      sets.push(`is_favorite = $${params.length}`);
    }
    if (notes !== undefined) {
      params.push(notes);
      sets.push(`notes = $${params.length}`);
    }
    if (sets.length === 0) {
      return NextResponse.json({ error: 'nothing to update' }, { status: 400 });
    }
    params.push(id);
    const { rows, rowCount } = await query(
      `UPDATE email_analyzer_subject_lines SET ${sets.join(', ')}
        WHERE id = $${params.length} RETURNING *`,
      params,
    );
    if (!rowCount) return NextResponse.json({ error: 'not found' }, { status: 404 });
    return NextResponse.json({ subject: rows[0] });
  } catch (err) {
    console.error('[subject-lines] PATCH error:', (err as Error).message);
    return NextResponse.json({ error: 'Failed to update' }, { status: 500 });
  }
}

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

  try {
    const id = new URL(request.url).searchParams.get('id');
    if (!id) return NextResponse.json({ error: 'id required' }, { status: 400 });
    const { rowCount } = await query(
      `DELETE FROM email_analyzer_subject_lines WHERE id = $1`,
      [id],
    );
    if (!rowCount) return NextResponse.json({ error: 'not found' }, { status: 404 });
    return NextResponse.json({ deleted: true, id });
  } catch (err) {
    console.error('[subject-lines] DELETE error:', (err as Error).message);
    return NextResponse.json({ error: 'Failed to delete' }, { status: 500 });
  }
}