// POST /api/voice/tts
//   Body: { text, voice?, provider?, project_id?, save_to_disk?, format? }
//   Returns audio bytes streamed with the right content-type.
//
// Rate-limited at 60/hour through the marketplace voice_speak tool plumbing —
// this route is a thin wrapper around lib/tts.js that DOES NOT proxy through
// executeRegistryTool (the marketplace gate is enforced for agents using the
// tool; this route is for direct UI playback).

import { synthesizeSpeech, ttsProvidersConfigured, TTS_PROVIDERS } from '../../../../lib/tts.js';
import { checkLimit, recordCall } from '../../../../lib/tool-rate-limits.js';

export const dynamic = 'force-dynamic';
export const runtime = 'nodejs';

const ROUTE_RATE_LIMIT = { window_seconds: 3600, max: 120 };

export async function GET() {
  return Response.json({
    providers_configured: ttsProvidersConfigured(),
    providers_supported: TTS_PROVIDERS,
  });
}

export async function POST(request) {
  let body;
  try {
    body = await request.json();
  } catch {
    return Response.json({ error: 'invalid JSON body' }, { status: 400 });
  }

  const text = String(body?.text || '').trim();
  if (!text) return Response.json({ error: 'text is required' }, { status: 400 });
  if (text.length > 4000) return Response.json({ error: 'text too long (max 4000)' }, { status: 413 });

  // Reuse the rate-limiter table with a synthetic tool name so the dashboard
  // route is rate-limited independently from the agent-facing voice_speak tool.
  const rateTool = { rate_limit: ROUTE_RATE_LIMIT };
  const limit = checkLimit('voice_tts_route', null, rateTool);
  if (!limit.ok) {
    return Response.json(
      { error: 'rate_limited', retry_after_seconds: limit.retry_after_seconds },
      { status: 429, headers: { 'Retry-After': String(limit.retry_after_seconds) } },
    );
  }

  let result;
  try {
    result = await synthesizeSpeech({
      text,
      provider: body.provider,
      voice: body.voice,
      model: body.model,
      format: body.format,
      project_id: body.project_id || null,
      save_to_disk: Boolean(body.save_to_disk),
      agent_id: null,
    });
  } catch (err) {
    return Response.json({ error: String(err?.message || err) }, { status: 502 });
  }

  recordCall('voice_tts_route', null, rateTool);

  return new Response(result.audio_buffer, {
    status: 200,
    headers: {
      'Content-Type': result.mime_type,
      'Content-Length': String(result.audio_buffer.length),
      'X-Provider': result.provider,
      'X-Voice': result.voice,
      'X-Model': result.model,
      'X-Disk-File-Id': result.disk_file?.id || '',
      'Cache-Control': 'no-store',
    },
  });
}
