import { defineMiddleware } from 'astro:middleware'

import { resolveInternalApiBaseUrl } from './lib/api/client'
import {
  MAINTENANCE_ACCESS_COOKIE_NAME,
  sanitizeMaintenanceReturnTo,
  shouldBypassMaintenance,
} from './lib/maintenance'

interface MaintenanceStatusResponse {
  maintenance_mode_enabled?: boolean
  access_granted?: boolean
}

async function fetchMaintenanceStatus(url: URL, accessToken?: string): Promise<MaintenanceStatusResponse> {
  const response = await fetch(`${resolveInternalApiBaseUrl(url)}/site_settings/maintenance/status`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      accessToken: accessToken?.trim() || undefined,
    }),
  })

  if (!response.ok) {
    throw new Error(`Maintenance status request failed: ${response.status}`)
  }

  return response.json() as Promise<MaintenanceStatusResponse>
}

export const onRequest = defineMiddleware(async (context, next) => {
  const { url, cookies, redirect } = context

  if (shouldBypassMaintenance(url.pathname)) {
    return next()
  }

  try {
    const accessToken = cookies.get(MAINTENANCE_ACCESS_COOKIE_NAME)?.value
    const status = await fetchMaintenanceStatus(url, accessToken)
    const maintenanceModeEnabled = Boolean(status.maintenance_mode_enabled)
    const accessGranted = Boolean(status.access_granted)

    if (!maintenanceModeEnabled || accessGranted) {
      return next()
    }
  } catch (error) {
    console.error('Failed to resolve maintenance mode status:', error)
  }

  const returnTo = sanitizeMaintenanceReturnTo(`${url.pathname}${url.search}`)
  return redirect(`/maintenance?returnTo=${encodeURIComponent(returnTo)}`, 302)
})
