import { cookies } from 'next/headers';
import { NextRequest, NextResponse } from 'next/server';

// ---------------------------------------------------------------------------
// Catch-all proxy route handler
// ---------------------------------------------------------------------------
// Every authenticated client-side API call goes through this proxy.
// It reads the `honeydue-token` httpOnly cookie and forwards the request to the
// Go API with an Authorization header.
// ---------------------------------------------------------------------------

const API_BASE_URL =
  process.env.API_URL ||
  process.env.NEXT_PUBLIC_API_URL ||
  'https://honeyDue.treytartt.com/api';

/**
 * Build the target URL from the catch-all path segments.
 * e.g.  /api/proxy/tasks/123/  ->  https://honeyDue.treytartt.com/api/tasks/123/
 */
function buildTargetUrl(request: NextRequest, pathSegments: string[]): string {
  const path = `/${pathSegments.join('/')}`;
  // Ensure trailing slash (Go API requires it)
  const normalizedPath = path.endsWith('/') ? path : `${path}/`;

  // Forward query string if present
  const search = request.nextUrl.search;
  return `${API_BASE_URL}${normalizedPath}${search}`;
}

/**
 * Build headers to forward to Go API.
 * Strips hop-by-hop headers and adds Authorization from cookie.
 */
async function buildHeaders(request: NextRequest): Promise<Headers> {
  const headers = new Headers();

  // Forward select request headers
  const forwardHeaders = [
    'content-type',
    'accept',
    'x-timezone',
    'x-requested-with',
    'if-none-match',
  ];

  for (const name of forwardHeaders) {
    const value = request.headers.get(name);
    if (value) {
      headers.set(name, value);
    }
  }

  // Attach auth token from httpOnly cookie
  const cookieStore = await cookies();
  const token = cookieStore.get('honeydue-token')?.value;
  if (token) {
    headers.set('Authorization', `Token ${token}`);
  }

  return headers;
}

/**
 * Proxy a request to the Go API and return the response.
 */
async function proxyRequest(
  request: NextRequest,
  pathSegments: string[],
): Promise<NextResponse> {
  const targetUrl = buildTargetUrl(request, pathSegments);
  const headers = await buildHeaders(request);

  // Build fetch options
  const fetchOptions: RequestInit = {
    method: request.method,
    headers,
    // Do not let Next.js cache proxy requests
    cache: 'no-store',
  };

  // Forward request body for methods that typically have one
  if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(request.method)) {
    const contentType = request.headers.get('content-type') || '';

    if (contentType.includes('multipart/form-data')) {
      // Stream the raw body for multipart uploads
      fetchOptions.body = await request.arrayBuffer();
    } else if (contentType.includes('application/json')) {
      fetchOptions.body = await request.text();
    } else {
      // Fallback: forward raw body
      fetchOptions.body = await request.arrayBuffer();
    }
  }

  try {
    const upstream = await fetch(targetUrl, fetchOptions);

    // Build response headers to forward back to the client
    const responseHeaders = new Headers();
    const passHeaders = [
      'content-type',
      'etag',
      'cache-control',
      'content-disposition',
    ];
    for (const name of passHeaders) {
      const value = upstream.headers.get(name);
      if (value) {
        responseHeaders.set(name, value);
      }
    }

    // Handle 304 Not Modified (no body)
    if (upstream.status === 304) {
      return new NextResponse(null, {
        status: 304,
        headers: responseHeaders,
      });
    }

    // Handle 204 No Content
    if (upstream.status === 204) {
      return new NextResponse(null, {
        status: 204,
        headers: responseHeaders,
      });
    }

    // Stream the upstream body back
    const body = await upstream.arrayBuffer();
    return new NextResponse(body, {
      status: upstream.status,
      headers: responseHeaders,
    });
  } catch (error) {
    console.error('[proxy] Upstream request failed:', error);
    return NextResponse.json(
      { error: 'Failed to reach API server' },
      { status: 502 },
    );
  }
}

// ---------------------------------------------------------------------------
// HTTP method handlers
// ---------------------------------------------------------------------------

export async function GET(
  request: NextRequest,
  { params }: { params: Promise<{ path: string[] }> },
) {
  const { path } = await params;
  return proxyRequest(request, path);
}

export async function POST(
  request: NextRequest,
  { params }: { params: Promise<{ path: string[] }> },
) {
  const { path } = await params;
  return proxyRequest(request, path);
}

export async function PUT(
  request: NextRequest,
  { params }: { params: Promise<{ path: string[] }> },
) {
  const { path } = await params;
  return proxyRequest(request, path);
}

export async function PATCH(
  request: NextRequest,
  { params }: { params: Promise<{ path: string[] }> },
) {
  const { path } = await params;
  return proxyRequest(request, path);
}

export async function DELETE(
  request: NextRequest,
  { params }: { params: Promise<{ path: string[] }> },
) {
  const { path } = await params;
  return proxyRequest(request, path);
}
