// api/suno.ts
//
// Thin relay for *any* request that hits `/api/suno/**`
// → forwards it to `${process.env.SUNO_BASE_URL}/**`
// while injecting `Authorization: Bearer ${SUNO_API_KEY}`.
//
// • Works in Vercel Edge runtime (zero cold-start for streams)
// • Handles CORS pre-flight locally
// • Preserves streaming bodies (SSE, multipart, etc.)
// • Mirrors most request properties (method, query, headers)
//

export const config = { runtime: 'edge' };

const SUNO_HOST = (process.env.SUNO_BASE_URL ?? '').replace(/\/+$/, '');
const SUNO_KEY = process.env.SUNO_API_KEY;

// Simple CORS helper
function cors(req: Request): Headers {
  const h = new Headers();
  h.set('Access-Control-Allow-Origin', req.headers.get('origin') ?? '*');
  h.set(
    'Access-Control-Allow-Headers',
    req.headers.get('access-control-request-headers') ??
      'authorization,content-type'
  );
  h.set(
    'Access-Control-Allow-Methods',
    req.headers.get('access-control-request-method') ??
      'GET,POST,PUT,PATCH,DELETE,OPTIONS'
  );
  h.set('Access-Control-Max-Age', '86400');
  return h;
}

async function readRawBody(req: Request): Promise<Buffer> {
  // If body is a stream
  const body = req.body as unknown;
  if (body && typeof body === 'object' && 'getReader' in body) {
    const chunks: Buffer[] = [];
    const reader = (body as ReadableStream).getReader();
    try {
      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        chunks.push(Buffer.from(value));
      }
    } finally {
      reader.releaseLock();
    }
    return Buffer.concat(chunks);
  }

  // Fallback for empty or unknown body types
  return Buffer.from([]);
}

export default async function handler(req: Request): Promise<Response> {
  // 1️⃣  Pre-flight CORS
  if (req.method === 'OPTIONS') {
    return new Response(null, { status: 204, headers: cors(req) });
  }

  if (!SUNO_HOST || !SUNO_KEY) {
    return new Response('Suno relay not configured', { status: 500 });
  }

  // 2️⃣  Derive the upstream URL (strip `/api/suno`)
  const url = new URL(req.url);
  const upstreamURL = `${SUNO_HOST}${url.pathname.slice('/suno'.length)}${
    url.search
  }`;

  const rawBuffer =
    req.method === 'GET' || req.method === 'HEAD'
      ? undefined
      : await readRawBody(req);
  const rawBody = rawBuffer?.toString('utf8');

  // 3️⃣  Forward the request
  const upstream = await fetch(upstreamURL, {
    method: req.method,
    headers: (() => {
      const out = new Headers();
      out.set('Authorization', `Bearer ${SUNO_KEY}`);
      out.set('Content-Type', 'application/json');
      if (rawBody !== undefined) {
        out.set(
          'Content-Length',
          Buffer.byteLength(rawBody, 'utf8').toString()
        );
      }
      return out;
    })(),
    // Only pass body for methods that can have one
    body: rawBody,
    redirect: 'manual',
  });

  // 4️⃣  Mirror status & stream body
  const headers = cors(req);
  upstream.headers.forEach((v, k) => headers.set(k, v));
  // Ensure proxies don't buffer chunked responses
  headers.set('X-Accel-Buffering', 'no');

  return new Response(upstream.body, {
    status: upstream.status,
    statusText: upstream.statusText,
    headers,
  });
}
