export type SecurityHeader = { key: string; value: string }

const RECAPTCHA_HOSTS = [
  'https://www.google.com',
  'https://www.gstatic.com',
  'https://recaptcha.net',
] as const

function joinSpace(values: readonly string[]): string {
  return values.filter(Boolean).join(' ')
}

export function buildContentSecurityPolicy(opts: { isProd: boolean }): string {
  const recaptcha = joinSpace(RECAPTCHA_HOSTS)
  const scriptSrc = joinSpace([
    "'self'",
    "'unsafe-inline'",
    opts.isProd ? '' : "'unsafe-eval'",
    recaptcha,
  ])

  return [
    "default-src 'self'",
    `script-src ${scriptSrc}`,
    "style-src 'self' 'unsafe-inline'",
    "img-src 'self' data: blob: https:",
    "font-src 'self' data:",
    `connect-src 'self' blob: ${recaptcha}`,
    `frame-src 'self' ${recaptcha}`,
    "frame-ancestors 'none'",
    "base-uri 'self'",
    "form-action 'self'",
    "object-src 'none'",
    "worker-src 'self' blob:",
    "manifest-src 'self'",
    'upgrade-insecure-requests',
  ].join('; ')
}

export function buildSecurityHeaders(opts: {
  isProd: boolean
}): SecurityHeader[] {
  const headers: SecurityHeader[] = [
    {
      key: 'Content-Security-Policy',
      value: buildContentSecurityPolicy(opts),
    },
    { key: 'X-Frame-Options', value: 'DENY' },
    { key: 'X-Content-Type-Options', value: 'nosniff' },
    { key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
    { key: 'X-DNS-Prefetch-Control', value: 'off' },
    { key: 'Cross-Origin-Opener-Policy', value: 'same-origin' },
    {
      key: 'Permissions-Policy',
      value: [
        'camera=()',
        'microphone=()',
        'geolocation=()',
        'payment=()',
        'usb=()',
        'magnetometer=()',
        'gyroscope=()',
        'accelerometer=()',
        'interest-cohort=()',
      ].join(', '),
    },
  ]

  if (opts.isProd) {
    headers.push({
      key: 'Strict-Transport-Security',
      value: 'max-age=63072000; includeSubDomains; preload',
    })
  }

  return headers
}
