import { NextResponse, type NextRequest } from 'next/server'
import { updateSession } from '@/utils/supabase/middleware'

/*
  O endereço do conector (mcp.ktalogu.com.br) chega neste mesmo servidor.

  Nele só existem o servidor MCP e as portas do login por botão: a raiz e
  `/mcp` levam para `/api/mcp`, e todo o resto responde 404. O painel não é
  servido por esse endereço, e por isso a sessão por cookie nem é conferida
  aqui: quem identifica o pedido é a chave.

  Qual endereço foi pedido de verdade: o Apache, que fica na frente, escreve o
  endereço real no FIM do `X-Forwarded-Host` (o que o visitante mandar nesse
  cabeçalho fica antes), e com `ProxyPreserveHost` ele também vem no `Host`.
  Por isso só valem esses dois lugares. Olhar o cabeçalho inteiro deixaria
  qualquer um mandar `X-Forwarded-Host: mcp.x` para o endereço do painel e
  receber um 404 no lugar de um arquivo, e um 404 desses guardado pelo
  Cloudflare tiraria o arquivo do ar para todo mundo por alguns minutos.
*/
function enderecoDoConector(request: NextRequest): string | null {
  const encaminhados = (request.headers.get('x-forwarded-host') || '').split(',')
  const reais = [encaminhados[encaminhados.length - 1], request.headers.get('host') || '']
  for (const host of reais) {
    const limpo = host.trim().toLowerCase()
    if (limpo.startsWith('mcp.')) return limpo
  }
  return null
}

/*
  As portas do login por botão que o PROGRAMA chama (o Claude, o ChatGPT): os
  dois cartões de visita, o registro, a troca do código e o desligar. Nenhuma
  usa a sessão do navegador, e por isso passam direto, nos dois endereços.
*/
function ehPortaDoLoginPorBotao(caminho: string) {
  return (
    caminho === '/oauth/register' ||
    caminho === '/oauth/token' ||
    caminho === '/oauth/revoke' ||
    caminho === '/.well-known/oauth-protected-resource' ||
    caminho.startsWith('/.well-known/oauth-protected-resource/') ||
    caminho === '/.well-known/oauth-authorization-server' ||
    caminho.startsWith('/.well-known/oauth-authorization-server/')
  )
}

/* O caminho pelo qual o programa chegou ao conector vai anotado para a rota,
   que precisa dele para dizer onde está o cartão de visita. O valor é sempre
   escrito aqui: o que o programa mandar nesse cabeçalho é descartado. */
const CAMINHO_DO_CONECTOR = 'x-ktalogu-caminho-do-conector'

function comOCaminho(request: NextRequest, caminho: string) {
  const cabecalhos = new Headers(request.headers)
  cabecalhos.set(CAMINHO_DO_CONECTOR, caminho)
  return { request: { headers: cabecalhos } }
}

export async function proxy(request: NextRequest) {
  const caminho = request.nextUrl.pathname
  const conector = enderecoDoConector(request)

  if (conector) {
    if (caminho === '/api/mcp') return NextResponse.next(comOCaminho(request, caminho))
    if (caminho === '/' || caminho === '/mcp') {
      const destino = request.nextUrl.clone()
      destino.pathname = '/api/mcp'
      return NextResponse.rewrite(destino, comOCaminho(request, caminho))
    }
    if (ehPortaDoLoginPorBotao(caminho)) return NextResponse.next()

    /* Programa antigo, que não lê os cartões de visita, procura estas portas
       direto na raiz do conector. */
    if (caminho === '/register' || caminho === '/token') {
      const destino = request.nextUrl.clone()
      destino.pathname = `/oauth${caminho}`
      return NextResponse.rewrite(destino)
    }
    /* A tela de permitir mora no painel, que é onde a pessoa está logada. */
    if (caminho === '/authorize' || caminho === '/oauth/authorize') {
      return NextResponse.redirect(`https://${conector.replace(/^mcp\./, 'admin.')}/oauth/authorize${request.nextUrl.search}`, 307)
    }

    /* `no-store`: esta recusa nunca pode ser guardada por quem fica no caminho. */
    return NextResponse.json({ error: 'not_found' }, { status: 404, headers: { 'Cache-Control': 'no-store' } })
  }

  /* No endereço do painel (e na máquina de quem desenvolve) a rota do conector
     e as portas do programa também atendem, sem passar pela sessão. */
  if (caminho === '/api/mcp') return NextResponse.next(comOCaminho(request, caminho))
  if (ehPortaDoLoginPorBotao(caminho)) return NextResponse.next()

  const resposta = await updateSession(request)

  if (caminho === '/oauth/authorize') {
    /* A tela de permitir nunca abre dentro de outra página: é o que impede um
       site de escondê-la atrás de um botão falso e colher o clique. */
    resposta.headers.set('X-Frame-Options', 'DENY')
    resposta.headers.set('Content-Security-Policy', "frame-ancestors 'none'")
    resposta.headers.set('Referrer-Policy', 'no-referrer')
    resposta.headers.set('Cache-Control', 'no-store')
  }
  if (caminho === '/dashboard/design') {
    /* A tela do KtaloguDesign fica "isolada": é o que libera os vários núcleos
       para tirar o fundo da foto (sem isso o navegador só deixa um, ~3x mais
       lento). "credentialless" deixa as fotos e fontes de outros sites
       carregarem (sem cookies). A tela não tem iframe de outro site; quem sai
       dela para outra tela recarrega (dashboard/layout.tsx), para as outras
       telas não herdarem o isolamento. */
    resposta.headers.set('Cross-Origin-Opener-Policy', 'same-origin')
    resposta.headers.set('Cross-Origin-Embedder-Policy', 'credentialless')
  }
  return resposta
}

export const config = {
  matcher: [
    /*
     * Match all request paths except for the ones starting with:
     * - _next/static (static files)
     * - _next/image (image optimization files)
     * - favicon.ico (favicon file)
     * Feel free to modify this pattern to include more paths.
     */
    '/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
  ],
}
