import { createLogger } from '@sim/logger'
import { normalizeEmail } from '@sim/utils/string'
import type { NextRequest } from 'next/server'
import { NextResponse } from 'next/server'
import { publicFileSSOContract } from '@/lib/api/contracts/public-shares'
import { parseRequest } from '@/lib/api/server'
import type { TokenBucketConfig } from '@/lib/core/rate-limiter'
import { RateLimiter } from '@/lib/core/rate-limiter'
import { isEmailAllowed } from '@/lib/core/security/deployment'
import { generateRequestId, getClientIp } from '@/lib/core/utils/request'
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'
import { resolveActiveShareByToken } from '@/lib/public-shares/share-manager'

export const dynamic = 'force-dynamic'
export const runtime = 'nodejs'

const logger = createLogger('PublicFileSSOAPI')

const rateLimiter = new RateLimiter()

const SSO_IP_RATE_LIMIT: TokenBucketConfig = {
  maxTokens: 20,
  refillRate: 20,
  refillIntervalMs: 15 * 60_000,
}

/**
 * POST /api/files/public/[token]/sso
 * Reports whether an email is on the allow-list for an SSO-gated share. The actual
 * authentication is the global Sim session (checked at the page/route gate).
 */
export const POST = withRouteHandler(
  async (request: NextRequest, context: { params: Promise<{ token: string }> }) => {
    const requestId = generateRequestId()

    const ip = getClientIp(request)
    const ipRateLimit = await rateLimiter.checkRateLimitDirect(
      `file-sso:ip:${ip}`,
      SSO_IP_RATE_LIMIT
    )
    if (!ipRateLimit.allowed) {
      logger.warn(`[${requestId}] SSO eligibility rate limit exceeded from ${ip}`)
      const response = NextResponse.json(
        { error: 'Too many requests. Please try again later.' },
        { status: 429 }
      )
      response.headers.set(
        'Retry-After',
        String(Math.ceil((ipRateLimit.retryAfterMs ?? SSO_IP_RATE_LIMIT.refillIntervalMs) / 1000))
      )
      return response
    }

    const parsed = await parseRequest(publicFileSSOContract, request, context)
    if (!parsed.success) return parsed.response
    const { token } = parsed.data.params
    const email = normalizeEmail(parsed.data.body.email)

    const resolved = await resolveActiveShareByToken(token)
    if (!resolved) {
      return NextResponse.json({ error: 'Not found' }, { status: 404 })
    }
    if (resolved.share.authType !== 'sso') {
      return NextResponse.json({ error: 'This file is not configured for SSO' }, { status: 400 })
    }

    const allowedEmails = Array.isArray(resolved.share.allowedEmails)
      ? (resolved.share.allowedEmails as string[])
      : []
    return NextResponse.json({ eligible: isEmailAllowed(email, allowedEmails) })
  }
)
