import { NextRequest, NextResponse } from 'next/server'
import { jwtVerify } from 'jose/jwt/verify'

// Paths that bypass auth entirely
const PUBLIC_PATHS = [
  '/auth',                    // investor login pages
  '/api/auth',                // investor auth API
  '/api/health',
  '/api/admin-auth',          // admin login API
  '/pitch-admin/login',       // admin login page
  '/p',                       // short link redirects — must be public so uninvited users can follow magic links
  '/_next',
  '/manifest.json',
  '/sw.js',
  '/icons',
  '/screenshots',             // SDK demo screenshots: public marketing assets. Must bypass auth because the next/image optimizer fetches them server-side without investor cookies.
  '/team',                    // Team photos: must bypass auth for next/image optimizer
  '/favicon.ico',
]

// Paths gated on the admin session cookie
const ADMIN_GATED_PREFIXES = ['/pitch-admin', '/api/admin', '/pitch-preview', '/api/preview-data']

function isPublicPath(pathname: string): boolean {
  return PUBLIC_PATHS.some(p => pathname === p || pathname.startsWith(p + '/'))
}

function isAdminGatedPath(pathname: string): boolean {
  return ADMIN_GATED_PREFIXES.some(p => pathname === p || pathname.startsWith(p + '/'))
}

const ADMIN_AUDIENCE = 'pitch-admin'

export async function middleware(request: NextRequest) {
  const { pathname } = request.nextUrl
  const secret = process.env.PITCH_JWT_SECRET

  // Skip all auth in local dev when no secret is configured
  if (!secret && process.env.NODE_ENV === 'development') {
    return NextResponse.next()
  }

  // Allow public paths
  if (isPublicPath(pathname)) {
    return NextResponse.next()
  }

  // ----- Admin-gated routes -----
  if (isAdminGatedPath(pathname)) {
    // Allow bearer-secret CLI access on /api/admin/* — validate the token here,
    // not just in the route handler, to avoid any unprotected route slipping through.
    if (pathname.startsWith('/api/admin') && request.headers.get('authorization')?.startsWith('Bearer ')) {
      const bearerToken = request.headers.get('authorization')!.slice(7)
      const adminSecret = process.env.PITCH_ADMIN_SECRET
      if (!adminSecret || bearerToken !== adminSecret) {
        return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
      }
      return NextResponse.next()
    }

    const adminToken = request.cookies.get('pitch_admin_session')?.value
    if (!adminToken || !secret) {
      if (pathname.startsWith('/api/')) {
        return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
      }
      return NextResponse.redirect(new URL('/pitch-admin/login', request.url))
    }

    try {
      await jwtVerify(adminToken, new TextEncoder().encode(secret), { audience: ADMIN_AUDIENCE })
      return NextResponse.next()
    } catch {
      if (pathname.startsWith('/api/')) {
        return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
      }
      const response = NextResponse.redirect(new URL('/pitch-admin/login', request.url))
      response.cookies.delete('pitch_admin_session')
      return response
    }
  }

  // ----- Allow admins to access investor routes (e.g. /api/chat in preview) -----
  const adminFallback = request.cookies.get('pitch_admin_session')?.value
  if (adminFallback && secret) {
    try {
      await jwtVerify(adminFallback, new TextEncoder().encode(secret), { audience: ADMIN_AUDIENCE })
      return NextResponse.next()
    } catch {
      // Invalid admin token, fall through to investor auth
    }
  }

  // ----- Investor-gated routes (everything else) -----
  const token = request.cookies.get('pitch_session')?.value

  if (!token || !secret) {
    return NextResponse.redirect(new URL('/auth', request.url))
  }

  try {
    const { payload } = await jwtVerify(token, new TextEncoder().encode(secret))

    const response = NextResponse.next()
    response.headers.set('x-investor-id', payload.sub as string)
    response.headers.set('x-investor-email', payload.email as string)
    response.headers.set('x-session-id', payload.sessionId as string)

    const exp = payload.exp as number
    const now = Math.floor(Date.now() / 1000)
    const timeLeft = exp - now
    if (timeLeft < 900 && timeLeft > 0) {
      response.headers.set('x-token-refresh-needed', 'true')
    }

    return response
  } catch {
    const response = NextResponse.redirect(new URL('/auth', request.url))
    response.cookies.delete('pitch_session')
    return response
  }
}

export const config = {
  matcher: ['/((?!_next/static|_next/image).*)'],
}
