import { test } from 'node:test';
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import { parseFeed } from '../src/feeds/parser.ts';
import { normalizeFeed } from '../src/feeds/normalizer.ts';

const fx = (name: string) => readFileSync(new URL(`./fixtures/${name}`, import.meta.url), 'utf8');

test('parses RSS fixture', () => {
  const parsed = parseFeed(fx('rss.xml'), 'application/rss+xml');
  assert.equal(parsed.type, 'rss');
  assert.equal(parsed.items.length, 2);
  assert.equal(parsed.items[0].guid, 'guid-1');
});

test('parses Atom fixture', () => {
  const parsed = parseFeed(fx('atom.xml'), 'application/atom+xml');
  assert.equal(parsed.type, 'atom');
  assert.equal(parsed.items.length, 1);
  assert.equal(parsed.items[0].title, 'Atom entry');
});

test('parses JSON Feed fixture', () => {
  const parsed = parseFeed(fx('feed.json'), 'application/json');
  assert.equal(parsed.type, 'json');
  assert.equal(parsed.items.length, 1);
  assert.equal(parsed.items[0].title, 'JSON item');
});

test('malformed XML throws', () => {
  assert.throws(
    () => parseFeed(fx('malformed.xml'), 'application/xml'),
    /ParseError|invalid XML|unknown feed/,
  );
});

test('normalizes and sanitizes content', () => {
  const parsed = parseFeed(fx('rss.xml'), 'application/rss+xml');
  const norm = normalizeFeed(parsed, 'https://example.com/', '2024-01-05T00:00:00Z');
  assert.equal(norm.items[0].guid, 'guid-1');
  assert.match(norm.items[0].contentHtml, /noopener noreferrer nofollow/);
  assert.doesNotMatch(norm.items[0].contentHtml, /<script/);
});

test('dedup key prefers guid then hash', () => {
  const parsed = parseFeed(fx('rss.xml'), 'application/rss+xml');
  const norm = normalizeFeed(parsed, 'https://example.com/', '2024-01-05T00:00:00Z');
  assert.equal(norm.items[0].dedupKey, 'guid:guid-1');
  assert.match(norm.items[1].dedupKey, /^hash:/);
});

test('clamps future dates to fetch time', () => {
  const xml = `<?xml version="1.0"?><rss version="2.0"><channel><title>t</title><link>https://x.com</link><item><title>a</title><link>https://x.com/a</link><pubDate>Mon, 01 Jan 2030 00:00:00 GMT</pubDate></item></channel></rss>`;
  const parsed = parseFeed(xml, 'application/rss+xml');
  const norm = normalizeFeed(parsed, 'https://x.com/', '2024-01-05T00:00:00Z');
  assert.equal(norm.items[0].publishedAt, '2024-01-05T00:00:00.000Z');
});

test('missing date falls back to fetch time', () => {
  const xml = `<?xml version="1.0"?><rss version="2.0"><channel><title>t</title><link>https://x.com</link><item><title>a</title><link>https://x.com/a</link></item></channel></rss>`;
  const parsed = parseFeed(xml, 'application/rss+xml');
  const norm = normalizeFeed(parsed, 'https://x.com/', '2024-01-05T00:00:00Z');
  assert.equal(norm.items[0].publishedAt, '2024-01-05T00:00:00.000Z');
});
