// @ts-check

import mdx from '@astrojs/mdx'
import node from '@astrojs/node'
import sitemap from '@astrojs/sitemap'
import tailwindcss from '@tailwindcss/vite'
import { minimal2023Preset } from '@vite-pwa/assets-generator/config'
import AstroPWA from '@vite-pwa/astro'
import { defineConfig, envField } from 'astro/config'
import icon from 'astro-icon'
import devtoolsJson from 'vite-plugin-devtools-json'

import { postgresListener } from './src/lib/postgresListenerIntegration'
import { getServerEnvVariable } from './src/lib/serverEnvVariables'

const SITE_URL = getServerEnvVariable('SITE_URL')
const ONION_ADDRESS = getServerEnvVariable('ONION_ADDRESS')
const I2P_ADDRESS = getServerEnvVariable('I2P_ADDRESS')

export default defineConfig({
  site: SITE_URL,
  vite: {
    build: {
      sourcemap: true, // Enable sourcemaps on production, so users can inspect the code
    },

    plugins: [devtoolsJson(), tailwindcss()],
  },
  integrations: [
    postgresListener(),
    icon(),
    mdx(),
    AstroPWA({
      mode: 'development',
      base: '/',
      scope: '/',
      registerType: 'autoUpdate',
      manifest: {
        name: 'KYCnot.me',
        short_name: 'KYCnot.me',
        description: 'Find services that respect your privacy',
        theme_color: '#040505',
        background_color: '#171c1b',
        display: 'minimal-ui',
      },
      pwaAssets: {
        image: './public/favicon.svg',
        preset: {
          ...minimal2023Preset,
          maskable: {
            ...minimal2023Preset.maskable,
            padding: 0.1,
            resizeOptions: {
              ...minimal2023Preset.maskable.resizeOptions,
              background: '#3bdb78',
            },
          },
          apple: {
            ...minimal2023Preset.apple,
            padding: 0.1,
            resizeOptions: {
              ...minimal2023Preset.apple.resizeOptions,
              background: '#3bdb78',
            },
          },
        },
      },
      workbox: {
        navigateFallback: '/404',
        globPatterns: ['**/*.{js,css,html,ico,jpg,jpeg,png,svg,webp,avif}'],
      },
      strategies: 'injectManifest',
      srcDir: 'src',
      filename: 'sw.ts',
      devOptions: {
        enabled: true,
        type: 'module',
      },
      experimental: {
        directoryAndTrailingSlashHandler: true,
      },
    }),
    sitemap({
      filter: (page) => {
        const url = new URL(page)
        return !url.pathname.startsWith('/admin') && !url.pathname.startsWith('/account/impersonate')
      },
    }),
  ],
  adapter: node({
    mode: 'standalone',
  }),
  output: 'server',
  devToolbar: {
    enabled: false,
  },
  server: {
    open: false,
    allowedHosts: [new URL(SITE_URL).hostname],
    headers: {
      'Onion-Location': ONION_ADDRESS,
      'X-I2P-Location': I2P_ADDRESS,
      'X-Frame-Options': 'DENY',
      // Astro is working on this feature, when it's stable use it instead of this.
      // https://astro.build/blog/astro-590/#experimental-content-security-policy-support
      'Content-Security-Policy':
        SITE_URL === 'http://localhost:4321'
          ? "frame-ancestors 'none'; upgrade-insecure-requests"
          : "default-src 'self'; img-src 'self' *; frame-ancestors 'none'; upgrade-insecure-requests",
      'Strict-Transport-Security': 'max-age=31536000; includeSubdomains; preload;',
    },
  },
  image: {
    domains: [new URL(SITE_URL).hostname],
    remotePatterns: [{ protocol: 'https' }],
  },
  redirects: {
    // #region Redirects from old website
    '/pending': '/?verification=verified&verification=approved&verification=community',
    '/changelog': '/events',
    '/request': '/service-suggestion/new',
    '/service/[...slug]/summary': '/service/[...slug]/#scores',
    '/service/[...slug]/proof': '/service/[...slug]/#verification',
    '/attribute/[...slug]': '/attributes',
    '/attr/[...slug]': '/attributes',
    // #endregion

    '/service/[...slug]/review': '/service/[...slug]#comments',
  },
  env: {
    schema: {
      // Database (server-only, secret)
      DATABASE_URL: envField.string({
        context: 'server',
        access: 'secret',
        url: true,
        startsWith: 'postgresql://',
        default: 'postgresql://kycnot:kycnot@database:5432/kycnot?schema=public',
      }),
      // Public URLs (can be accessed from both server and client)
      SOURCE_CODE_URL: envField.string({
        context: 'client',
        access: 'public',
        url: true,
        optional: false,
      }),
      I2P_ADDRESS: envField.string({
        context: 'server',
        access: 'public',
        url: true,
        optional: false,
      }),
      ONION_ADDRESS: envField.string({
        context: 'server',
        access: 'public',
        url: true,
        optional: false,
      }),

      REDIS_URL: envField.string({
        context: 'server',
        access: 'secret',
        url: true,
        startsWith: 'redis://',
        default: 'redis://redis:6379',
      }),

      // Development tokens
      DEV_ADMIN_USER_SECRET_TOKEN: envField.string({
        context: 'server',
        access: 'secret',
        min: 1,
        default: 'admin',
      }),
      DEV_MODERATOR_USER_SECRET_TOKEN: envField.string({
        context: 'server',
        access: 'secret',
        min: 1,
        default: 'moderator',
      }),
      DEV_VERIFIED_USER_SECRET_TOKEN: envField.string({
        context: 'server',
        access: 'secret',
        min: 1,
        default: 'verified',
      }),
      DEV_NORMAL_USER_SECRET_TOKEN: envField.string({
        context: 'server',
        access: 'secret',
        min: 1,
        default: 'normal',
      }),
      DEV_SPAM_USER_SECRET_TOKEN: envField.string({
        context: 'server',
        access: 'secret',
        min: 1,
        default: 'spam',
      }),

      // Upload directory configuration
      UPLOAD_DIR: envField.string({
        context: 'server',
        access: 'secret',
        min: 1,
        default: './local_uploads',
      }),

      SITE_URL: envField.string({
        context: 'client',
        access: 'public',
        url: true,
        optional: false,
      }),

      DATABASE_UI_URL: envField.string({
        context: 'server',
        access: 'secret',
        url: true,
        optional: false,
      }),
      LOGS_UI_URL: envField.string({
        context: 'server',
        access: 'secret',
        url: true,
        optional: true,
      }),

      RELEASE_NUMBER: envField.number({
        context: 'server',
        access: 'public',
        int: true,
        optional: true,
      }),
      RELEASE_DATE: envField.string({
        context: 'server',
        access: 'public',
        optional: true,
      }),

      // Generated with `npx web-push generate-vapid-keys`
      VAPID_PUBLIC_KEY: envField.string({
        context: 'server',
        access: 'public',
        min: 1,
        optional: false,
      }),
      // Generated with `npx web-push generate-vapid-keys`
      VAPID_PRIVATE_KEY: envField.string({
        context: 'server',
        access: 'secret',
        min: 1,
        optional: false,
      }),
      VAPID_SUBJECT: envField.string({
        context: 'server',
        access: 'secret',
        min: 1,
        optional: false,
      }),
    },
  },
})
