import { NextRequest } from 'next/server'
import { oapiClient, sendResponse } from '../../oapi-client'

function buildUrl(path: string[]) {
  return `/v1/${path.join('/')}`
}

function buildFullForwardUrl(path: string[], query?: Record<string, string>) {
  const base = process.env.NOVA_BASE_URL || ''
  const normalizedBase = base.endsWith('/') ? base.slice(0, -1) : base
  const pathname = buildUrl(path)
  const url = new URL(`${normalizedBase}${pathname}`)
  Object.entries(query || {}).forEach(([key, value]) => {
    url.searchParams.set(key, value)
  })
  return url.toString()
}

function logForwardRequest(args: {
  method: string
  path: string[]
  query?: Record<string, string>
  body?: unknown
}) {
  const { method, path, query, body } = args
  console.log('[api/v1 proxy] forward', {
    method,
    url: buildFullForwardUrl(path, query),
    query: query || {},
    body: body ?? null,
  })
}

function logForwardResponse(method: string, path: string[], res: unknown) {
  const url = buildUrl(path)
  try {
    console.log('[api/v1 proxy] response', {
      method,
      url,
      raw: JSON.stringify(res, null, 2),
    })
  } catch {
    console.log('[api/v1 proxy] response', {
      method,
      url,
      raw: res,
    })
  }
}

function normalizeQuery(searchParams: URLSearchParams) {
  const query: Record<string, string> = {}

  searchParams.forEach((value, key) => {
    // params[task_id] -> task_id
    if (key.startsWith('params[') && key.endsWith(']')) {
      const realKey = key.slice(7, -1)
      if (realKey) query[realKey] = value
      return
    }
    query[key] = value
  })

  return query
}

export async function GET(
  req: NextRequest,
  { params }: { params: Promise<{ path: string[] }> },
) {
  const { path } = await params
  const query = normalizeQuery(req.nextUrl.searchParams)
  logForwardRequest({ method: 'GET', path, query })
  const res = await oapiClient.get(buildUrl(path), query)
  logForwardResponse('GET', path, res)
  return sendResponse(res)
}

export async function POST(
  req: Request,
  { params }: { params: Promise<{ path: string[] }> },
) {
  const body = req.body ? await req.json() : {}
  const { path } = await params
  logForwardRequest({ method: 'POST', path, body })
  const res = await oapiClient.post(buildUrl(path), body)
  logForwardResponse('POST', path, res)
  return sendResponse(res)
}

export async function PUT(
  req: Request,
  { params }: { params: Promise<{ path: string[] }> },
) {
  const body = req.body ? await req.json() : {}
  const { path } = await params
  logForwardRequest({ method: 'PUT', path, body })
  const res = await oapiClient.request({
    url: buildUrl(path),
    method: 'put',
    body,
  })
  logForwardResponse('PUT', path, res)
  return sendResponse(res)
}

export async function PATCH(
  req: Request,
  { params }: { params: Promise<{ path: string[] }> },
) {
  const body = req.body ? await req.json() : {}
  const { path } = await params
  logForwardRequest({ method: 'PATCH', path, body })
  const res = await oapiClient.request({
    url: buildUrl(path),
    method: 'patch',
    body,
  })
  logForwardResponse('PATCH', path, res)
  return sendResponse(res)
}

export async function DELETE(
  req: NextRequest,
  { params }: { params: Promise<{ path: string[] }> },
) {
  const { path } = await params
  const query = normalizeQuery(req.nextUrl.searchParams)
  logForwardRequest({ method: 'DELETE', path, query })
  const res = await oapiClient.delete(buildUrl(path), query)
  logForwardResponse('DELETE', path, res)
  return sendResponse(res)
}
