import assert from 'node:assert/strict';
import test from 'node:test';
import { publicationInternals } from './mindspace-publications.mjs';

test('normalizes safe long-page slugs', () => {
  assert.equal(publicationInternals.normalizeSlug('  product-intro-2026  '), 'product-intro-2026');
  assert.throws(
    () => publicationInternals.normalizeSlug('../private'),
    (error) => error.code === 'invalid_publish_input',
  );
  assert.throws(
    () => publicationInternals.normalizeSlug('中文地址'),
    (error) => error.code === 'invalid_publish_input',
  );
});

test('accepts all documented access modes', () => {
  for (const mode of [
    'public',
    'password',
    'private_link',
    'time_limited',
    'login_required',
    'owner_only',
  ]) {
    assert.equal(publicationInternals.normalizeAccessMode(mode), mode);
  }
  assert.throws(
    () => publicationInternals.normalizeAccessMode('team_only'),
    (error) => error.code === 'invalid_publish_input',
  );
});

test('hashes access passwords with a random salt', () => {
  const first = publicationInternals.hashPassword('Publish-Password-2026');
  const second = publicationInternals.hashPassword('Publish-Password-2026');
  assert.notEqual(first, second);
  assert.equal(publicationInternals.verifyPassword('Publish-Password-2026', first), true);
  assert.equal(publicationInternals.verifyPassword('wrong-password', first), false);
  assert.throws(
    () => publicationInternals.normalizePassword('short', true),
    (error) => error.code === 'invalid_publish_input',
  );
});

test('requires future expiry timestamps for time-limited pages', () => {
  const future = Date.now() + 60_000;
  assert.equal(publicationInternals.normalizeExpiresAt(future, true), future);
  assert.throws(
    () => publicationInternals.normalizeExpiresAt(Date.now() - 1, true),
    (error) => error.code === 'invalid_publish_input',
  );
});

test('classifies devices and strips referrer paths', () => {
  assert.equal(
    publicationInternals.deviceType('Mozilla/5.0 (iPhone; CPU iPhone OS 18_0) Mobile'),
    'mobile',
  );
  assert.equal(publicationInternals.deviceType('Googlebot/2.1'), 'bot');
  assert.equal(publicationInternals.deviceType('Mozilla/5.0 (Macintosh)'), 'desktop');
  assert.equal(
    publicationInternals.referrerHost('https://example.com/private/path?token=secret'),
    'example.com',
  );
  assert.equal(publicationInternals.referrerHost('not a url'), null);
});

test('warns for contact details and external links without silently hiding them', () => {
  const result = publicationInternals.scanContent(
    '联系 13812345678 或 hello@example.com，详情 https://example.com/path',
  );
  assert.equal(result.status, 'warned');
  assert.equal(result.riskLevel, 'medium');
  assert.equal(result.allowed, true);
  assert.deepEqual(
    result.findings.map((finding) => finding.type),
    ['phone', 'email', 'external_link'],
  );
  assert.doesNotMatch(result.findings[0].sampleMasked, /13812345678/);
});

test('deduplicates the same sensitive value repeated by summary and content', () => {
  const result = publicationInternals.scanContent(
    '摘要 qa@example.com\n正文 qa@example.com',
  );
  assert.equal(result.findings[0].occurrenceCount, 1);
});

test('blocks identity and bank-card numbers', () => {
  const result = publicationInternals.scanContent(
    '身份证 310101199001011234，银行卡 6222021234567890123',
  );
  assert.equal(result.status, 'blocked');
  assert.equal(result.riskLevel, 'high');
  assert.equal(result.allowed, false);
  assert.ok(result.findings.every((finding) => finding.blocking));
});

test('publicHomepageResponse summarizes public cards and total views', () => {
  const result = publicationInternals.publicHomepageResponse(
    {
      id: 'user-1',
      slug: 'john',
      username: 'john',
      display_name: 'John',
    },
    [
      {
        id: 'pub-1',
        page_id: 'page-1',
        title: '第一篇',
        summary: '摘要一',
        template_id: 'report',
        public_url: '/u/john/pages/one',
        url_slug: 'one',
        view_count: 7,
        published_at: 100,
      },
      {
        id: 'pub-2',
        page_id: 'page-2',
        title: '第二篇',
        summary: '摘要二',
        template_id: 'editorial',
        public_url: '/u/john/pages/two',
        url_slug: 'two',
        view_count: 3,
        published_at: 200,
      },
    ],
  );
  assert.equal(result.owner.displayName, 'John');
  assert.equal(result.totalViews, 10);
  assert.equal(result.pageCount, 2);
  assert.equal(result.pages[0].publicUrl, '/u/john/pages/one');
});
