/**
 * Streaming Proxy Route
 * 
 * Forwards requests and streams responses back for SSE endpoints.
 * Auto-detects SSE based on response content-type.
 */

import { NextRequest } from 'next/server'

// Headers that should not be forwarded
const EXCLUDED_REQUEST_HEADERS = [
  'host',
  'connection',
  'content-length',
  'transfer-encoding',
  'keep-alive',
  'upgrade',
  'proxy-connection',
  'proxy-authorization',
]

export async function POST(request: NextRequest) {
  const startTime = Date.now()
  
  try {
    const body = await request.json()
    
    const { url, method, headers, requestBody } = body as {
      url: string
      method: string
      headers: Record<string, string>
      requestBody?: string | null
    }

    if (!url) {
      return new Response(
        JSON.stringify({ error: 'URL is required' }),
        { status: 400, headers: { 'Content-Type': 'application/json' } }
      )
    }

    // Validate URL
    const parsedUrl = new URL(url)
    const allowedProtocols = ['http:', 'https:']
    if (!allowedProtocols.includes(parsedUrl.protocol)) {
      return new Response(
        JSON.stringify({ error: 'Invalid URL protocol' }),
        { status: 400, headers: { 'Content-Type': 'application/json' } }
      )
    }

    // Build headers for the proxied request
    const proxyHeaders: Record<string, string> = {}
    for (const [key, value] of Object.entries(headers || {})) {
      if (!EXCLUDED_REQUEST_HEADERS.includes(key.toLowerCase())) {
        proxyHeaders[key] = value
      }
    }

    // Make the proxied request
    const response = await fetch(url, {
      method: method || 'GET',
      headers: proxyHeaders,
      body: requestBody || undefined,
    })

    const contentType = response.headers.get('content-type') || ''
    
    // Check if this is a streaming response (SSE or similar)
    const isStreaming = 
      contentType.includes('text/event-stream') ||
      contentType.includes('application/x-ndjson') ||
      contentType.includes('application/stream+json')
    
    if (isStreaming && response.body) {
      // For streaming responses, wrap in our SSE format
      const encoder = new TextEncoder()
      
      // Send metadata first, then stream chunks
      const stream = new ReadableStream({
        async start(controller) {
          // Send metadata
          const metadata = {
            type: 'metadata',
            status: response.status,
            statusText: response.statusText,
            headers: Object.fromEntries(response.headers.entries()),
            contentType,
          }
          controller.enqueue(encoder.encode(`data: ${JSON.stringify(metadata)}\n\n`))
          
          const reader = response.body!.getReader()
          const decoder = new TextDecoder()
          let totalSize = 0
          
          try {
            while (true) {
              const { done, value } = await reader.read()
              
              if (done) {
                controller.enqueue(encoder.encode(`data: ${JSON.stringify({ type: 'done', totalSize })}\n\n`))
                controller.close()
                break
              }
              
              const chunk = decoder.decode(value, { stream: true })
              totalSize += value.length
              
              // Send chunk
              const chunkEvent = {
                type: 'chunk',
                data: chunk,
                size: value.length,
              }
              controller.enqueue(encoder.encode(`data: ${JSON.stringify(chunkEvent)}\n\n`))
            }
          } catch (error) {
            const errorEvent = {
              type: 'error',
              error: error instanceof Error ? error.message : 'Stream error',
            }
            controller.enqueue(encoder.encode(`data: ${JSON.stringify(errorEvent)}\n\n`))
            controller.close()
          }
        },
      })

      return new Response(stream, {
        headers: {
          'Content-Type': 'text/event-stream',
          'Cache-Control': 'no-cache',
          'Connection': 'keep-alive',
        },
      })
    }

    // For non-streaming responses, return as JSON
    const responseBody = await response.text()
    const responseHeaders: Record<string, string> = {}
    response.headers.forEach((value, key) => {
      responseHeaders[key] = value
    })

    return new Response(
      JSON.stringify({
        status: response.status,
        statusText: response.statusText,
        headers: responseHeaders,
        body: responseBody,
        size: new Blob([responseBody]).size,
        responseTime: Date.now() - startTime,
        isStreaming: false,
      }),
      {
        headers: { 'Content-Type': 'application/json' },
      }
    )
  } catch (error) {
    return new Response(
      JSON.stringify({
        status: 0,
        statusText: 'Proxy Error',
        error: error instanceof Error ? error.message : 'Proxy request failed',
      }),
      { status: 500, headers: { 'Content-Type': 'application/json' } }
    )
  }
}
