import test from 'node:test'
import assert from 'node:assert/strict'

import {
  RuntimeConfigValidationError,
  assertRuntimeConfigValid,
  validateRuntimeConfig,
} from './runtime-validation.js'
import { deepMerge } from './runtime-merge.js'
import type { RuntimeConfig } from '../types/runtime-config.js'

test('validateRuntimeConfig allows missing admin credentials outside production', () => {
  const issues = validateRuntimeConfig(
    createRuntimeConfig({
      admin: {
        sessionSecret: '',
        defaultUsers: [],
      },
    }),
    {
      env: { NODE_ENV: 'development' },
    },
  )

  assert.deepEqual(issues, [])
})

test('validateRuntimeConfig requires admin credentials in production', () => {
  const issues = validateRuntimeConfig(
    createRuntimeConfig({
      admin: {
        sessionSecret: '',
        defaultUsers: [],
      },
    }),
    {
      env: { NODE_ENV: 'production' },
    },
  )

  assert.deepEqual(
    issues.map((issue) => issue.path),
    ['admin.sessionSecret', 'admin.defaultUsers'],
  )
})

test('validateRuntimeConfig rejects unsafe production placeholders', () => {
  const issues = validateRuntimeConfig(
    createRuntimeConfig({
      admin: {
        sessionSecret: 'change-me-long-random-session-secret',
        defaultUsers: [
          {
            username: 'admin',
            password: 'change-me-admin-password',
            role: 'admin',
          },
        ],
      },
    }),
    {
      env: { NODE_ENV: 'production' },
    },
  )

  assert.deepEqual(
    issues.map((issue) => issue.path),
    ['admin.sessionSecret', 'admin.defaultUsers[0].password'],
  )
})

test('validateRuntimeConfig accepts complete production config', () => {
  const issues = validateRuntimeConfig(createRuntimeConfig(), {
    env: { NODE_ENV: 'production' },
  })

  assert.deepEqual(issues, [])
})

test('validateRuntimeConfig rejects wildcard CORS in production', () => {
  const issues = validateRuntimeConfig(createRuntimeConfig({ cors: { allowedOrigins: ['*'] } }), {
    env: { NODE_ENV: 'production' },
  })

  assert.deepEqual(
    issues.map((issue) => issue.path),
    ['cors.allowedOrigins'],
  )
})

test('validateRuntimeConfig catches invalid numeric and url values', () => {
  const issues = validateRuntimeConfig(
    createRuntimeConfig({
      server: {
        port: 70000,
      },
      database: {
        maxConnections: 0,
      },
      orders: {
        claimBaseUrl: 'not-a-url',
        tokenTtlHours: -1,
      },
    }),
    {
      env: { NODE_ENV: 'development' },
    },
  )

  assert.deepEqual(
    issues.map((issue) => issue.path),
    ['server.port', 'database.maxConnections', 'orders.tokenTtlHours', 'orders.claimBaseUrl'],
  )
})

test('validateRuntimeConfig accepts zero claim token TTL for permanent links', () => {
  const issues = validateRuntimeConfig(
    createRuntimeConfig({
      orders: {
        tokenTtlHours: 0,
      },
    }),
    { env: { NODE_ENV: 'development' } },
  )

  assert.deepEqual(issues, [])
})

test('assertRuntimeConfigValid throws a readable validation error', () => {
  assert.throws(
    () => {
      assertRuntimeConfigValid(
        createRuntimeConfig({
          server: {
            port: 0,
          },
        }),
      )
    },
    (error) => {
      assert.equal(error instanceof RuntimeConfigValidationError, true)
      assert.match((error as Error).message, /运行时配置校验失败/)
      assert.match((error as Error).message, /server\.port/)
      return true
    },
  )
})

function createRuntimeConfig(overrides: Record<string, unknown> = {}): RuntimeConfig {
  return deepMerge(
    {
      server: {
        port: 3000,
      },
      data: {
        root: '/tmp/order-site',
      },
      logging: {
        level: 'info',
        integrationLevel: 'warn',
      },
      database: {
        url: 'postgres://postgres:postgres@postgres:5432/order_site',
        ssl: false,
        maxConnections: 10,
      },
      storage: {
        endpoint: 'http://minio:9000',
        bucket: 'order-site',
        accessKeyId: 'minioadmin',
        secretAccessKey: 'minioadmin',
        region: 'us-east-1',
        maxUploadSizeMb: 10,
      },
      orders: {
        claimBaseUrl: 'https://order.example.test/#/claim',
        tokenTtlHours: 24,
      },
      admin: {
        sessionSecret: '0123456789abcdef0123456789abcdef',
        sessionTtlHours: 12,
        defaultUsers: [
          {
            username: 'admin',
            password: 'Qp7xT2mN9vR4',
            role: 'admin',
          },
        ],
      },
      platforms: {
        ninetyone: {
          userId: '',
          secret: '',
          version: '1.0',
          shopId: '91kaquan',
          shopName: '91卡券',
          timestampToleranceSeconds: 600,
          cardsEncoding: 'aes-256-ecb-base64',
        },
        cloudtentacles: {
          baseUrl: 'https://123.207.217.176',
          timeoutMs: 5000,
          sendSmsPath: '/public/verif_code',
          loginPath: '/public/login',
          userInfoPath: '/user/info',
          assetPath: '/user/get_asset',
          permissionPath: '/user/get_permission',
          categoriesPath: '/categories/get',
          skuListPath: '/sku/list',
          skuBuyPath: '/sku/buy',
          skuUsePath: '/sku/use',
          knapsackPath: '/user/get_knapsack',
          vnListPath: '/vn/list',
          vnAppointPath: '/vn/appoint',
          vnGenerateLoginCodePath: '/vn/generate_login_code',
          vnVerifCodePath: '/public/vn_verif_code',
          vnVerifyLoginCodePath: '/vn/verify_login_code',
          vnBindUrlPath: '/vn/bind_url',
          vnBindInfoPath: '/vn/bind_info',
          vnBackPath: '/vn/back',
          bindUrlTtlSeconds: 600,
          bindUrlProbeIntervalSeconds: 30,
          bindUrlProbeTimeoutMs: 5000,
          bindUrlProbeUserAgent: '',
          bindUrlProbeEndpoint: 'https://comm.ams.game.qq.com/ide/',
          bindUrlProbeChartId: '323794',
          bindUrlProbeSubChartId: '323794',
          bindUrlProbeIdeToken: 'z90Syo',
          bindUrlProbeActivityUrl: '',
          bindUrlProbeReferer: 'https://gp.qq.com/',
          bindUrlProbeExtraCookie: '',
          publicKeyPem: '',
          clientSource: 'ct-client',
          deviceId: '08bc9d8c-fd15-48ea-bc00-8d754076cafc',
          deviceType: 1,
        },
      },
    },
    overrides,
  ) as RuntimeConfig
}
