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

import {
  formatLogEntry,
  formatLogTimestamp,
  normalizeLogLevel,
  resolveExpiredLogFilenames,
  resolveLogFilePath,
  shouldWriteLog,
} from './logger.js'

test('normalizeLogLevel falls back to info for unsupported values', () => {
  assert.equal(normalizeLogLevel('debug'), 'debug')
  assert.equal(normalizeLogLevel('WARN'), 'warn')
  assert.equal(normalizeLogLevel('verbose'), 'info')
  assert.equal(normalizeLogLevel(''), 'info')
})

test('shouldWriteLog respects configured minimum log level', () => {
  assert.equal(shouldWriteLog('debug', 'debug'), true)
  assert.equal(shouldWriteLog('info', 'debug'), true)
  assert.equal(shouldWriteLog('debug', 'info'), false)
  assert.equal(shouldWriteLog('info', 'warn'), false)
  assert.equal(shouldWriteLog('warn', 'warn'), true)
  assert.equal(shouldWriteLog('error', 'warn'), true)
})

test('shouldWriteLog at warn filters info-style integration noise', () => {
  // 与默认 LOG_INTEGRATION_LEVEL=warn 行为一致
  assert.equal(shouldWriteLog('info', 'warn'), false)
  assert.equal(shouldWriteLog('warn', 'warn'), true)
  assert.equal(shouldWriteLog('error', 'warn'), true)
})

test('resolveLogFilePath uses daily log file names by channel', () => {
  assert.match(resolveLogFilePath('app', '2026-05-28T00:00:19.194+08:00'), /app-2026-05-28\.log$/)
  assert.match(
    resolveLogFilePath('integration', '2026-05-28T00:00:19.194+08:00'),
    /integration-2026-05-28\.log$/,
  )
})

test('resolveLogFilePath uses local date for utc timestamps', () => {
  assert.match(resolveLogFilePath('app', '2026-05-27T16:00:19.194Z'), /app-2026-05-28\.log$/)
})

test('resolveExpiredLogFilenames keeps latest thirty days by default and ignores unknown files', () => {
  const expired = resolveExpiredLogFilenames(
    [
      'app-2026-05-30.log',
      'app-2026-05-01.log',
      'app-2026-04-30.log',
      'integration-2026-04-29.log',
      'app.log',
      'integration.log',
      'random.txt',
    ],
    '2026-05-30',
  )

  assert.deepEqual(expired, [
    'app-2026-04-30.log',
    'integration-2026-04-29.log',
    'app.log',
    'integration.log',
  ])
})

test('resolveExpiredLogFilenames supports explicit retention days', () => {
  const expired = resolveExpiredLogFilenames(
    ['app-2026-04-14.log', 'app-2026-04-08.log', 'app-2026-04-07.log'],
    '2026-04-14',
    7,
  )

  assert.deepEqual(expired, ['app-2026-04-07.log'])
})

test('resolveExpiredLogFilenames includes rotated files', () => {
  const expired = resolveExpiredLogFilenames(
    ['app-2026-04-14.1.log', 'app-2026-04-07.5.log', 'app-2026-04-14.log'],
    '2026-04-14',
    7,
  )

  assert.deepEqual(expired, ['app-2026-04-07.5.log'])
})

test('formatLogTimestamp renders readable local timestamp with timezone offset', () => {
  const rendered = formatLogTimestamp('2026-04-14T10:36:24.974Z')
  assert.match(rendered, /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3} [+-]\d{2}:\d{2}$/)
})

test('formatLogEntry prints readable one-line output for flat details', () => {
  const text = formatLogEntry(
    {
      time: '2026-04-14T10:36:24.974Z',
      level: 'info',
      scope: '[http/access]',
      message: 'request completed',
      pid: 4671,
      detail: {
        requestId: 'req-123',
        method: 'GET',
        statusCode: 401,
      },
    },
    { color: false },
  )

  assert.match(text, /INFO\s+\[http\/access\] request completed/)
  assert.match(text, /pid=4671/)
  assert.match(text, /requestId=req-123/)
  assert.match(text, /method=GET/)
  assert.match(text, /statusCode=401/)
  assert.doesNotMatch(text, /^\{/)
})

test('formatLogEntry prints nested detail blocks without ansi colors in file mode', () => {
  const text = formatLogEntry(
    {
      time: '2026-04-14T10:36:24.974Z',
      level: 'warn',
      scope: '[admin/auth]',
      message: '后台鉴权失败',
      pid: 4671,
      detail: {
        statusCode: 401,
        errorCode: 'admin_auth_required',
        error: {
          message: '未登录或登录已失效',
          stack: 'Error: test',
        },
      },
    },
    { color: false },
  )

  assert.match(text, /WARN\s+\[admin\/auth\] 后台鉴权失败/)
  assert.match(text, /statusCode=401/)
  assert.match(text, /errorCode=admin_auth_required/)
  assert.match(text, /\n  \{/)
  assert.match(text, /未登录或登录已失效/)
  assert.doesNotMatch(text, /\u001B\[/)
})

test('formatLogEntry masks sensitive fields in inline and nested details', () => {
  const text = formatLogEntry(
    {
      time: '2026-04-14T10:36:24.974Z',
      level: 'info',
      scope: '[security]',
      message: 'masked',
      pid: 4671,
      detail: {
        token: 'abcdef1234567890',
        authorization: 'Bearer abcdef1234567890',
        sign: '0123456789abcdef',
        jumpLink:
          'https://feifei.example.com/h5/bind?code=very-secret-code&token=very-secret-token',
        rawText:
          '{"token":"raw-json-token","sign":"raw-json-sign","h5":{"recharge_url":"https://feifei.example.com/h5/bind?code=raw-secret-code"}}',
        nested: {
          cookie: 'sessionid=abcdef1234567890',
          note: 'password=super-secret-value',
        },
      },
    },
    { color: false },
  )

  assert.doesNotMatch(text, /abcdef1234567890/)
  assert.doesNotMatch(text, /super-secret-value/)
  assert.doesNotMatch(text, /0123456789abcdef/)
  assert.doesNotMatch(text, /very-secret-code/)
  assert.doesNotMatch(text, /very-secret-token/)
  assert.doesNotMatch(text, /raw-json-token/)
  assert.doesNotMatch(text, /raw-json-sign/)
  assert.doesNotMatch(text, /raw-secret-code/)
  assert.match(text, /abcdef\*\*\*\*567890/)
  assert.match(text, /Bearer\*\*\*\*567890/)
  assert.match(text, /password=super-\*\*\*\*-value/)
})
