import test from 'node:test';
import assert from 'node:assert/strict';
import { briefing, getHot, getRedditConfig, getToken } from '../apis/sources/reddit.mjs';

test('Reddit reports missing OAuth credentials without network access', async () => {
  let calls = 0;
  const data = await briefing({
    env: {},
    delayMs: 0,
    fetchImpl: async () => {
      calls++;
      throw new Error('unexpected network access');
    },
  });

  assert.equal(calls, 0);
  assert.equal(data.status, 'no_credentials');
  assert.equal(data.error, 'missing_reddit_oauth_credentials');
  assert.deepEqual(data.missing, ['REDDIT_CLIENT_ID', 'REDDIT_CLIENT_SECRET']);
});

test('Reddit hot posts require OAuth token and never use public JSON fallback', async () => {
  const originalFetch = globalThis.fetch;
  let calledUrl = null;
  globalThis.fetch = async url => {
    calledUrl = url;
    throw new Error('unexpected public fallback');
  };

  try {
    const data = await getHot('worldnews');
    assert.equal(calledUrl, null);
    assert.equal(data.status, 'no_credentials');
    assert.equal(data.error, 'reddit_oauth_required');
  } finally {
    globalThis.fetch = originalFetch;
  }
});

test('Reddit classifies OAuth HTTP failure without exposing secrets', async () => {
  const result = await getToken({
    env: { REDDIT_CLIENT_ID: 'client-id', REDDIT_CLIENT_SECRET: 'client-secret' },
    fetchImpl: async () => ({
      ok: false,
      status: 401,
      text: async () => 'invalid client',
    }),
  });

  assert.equal(result.ok, false);
  assert.equal(result.status, 'auth_failed');
  assert.equal(result.error, 'reddit_oauth_http_401');
  assert.doesNotMatch(JSON.stringify(result), /client-secret/);
});

test('Reddit fetches hot posts through oauth.reddit.com when configured', async () => {
  const originalFetch = globalThis.fetch;
  const urls = [];
  globalThis.fetch = async url => {
    urls.push(String(url));
    if (String(url).includes('/api/v1/access_token')) {
      return {
        ok: true,
        status: 200,
        json: async () => ({ access_token: 'test-token' }),
      };
    }
    return {
      ok: true,
      status: 200,
      headers: { get: () => 'application/json' },
      text: async () => JSON.stringify({
        data: {
          children: [
            {
              data: {
                title: 'Market stress headline',
                score: 42,
                num_comments: 7,
                url: 'https://example.test/post',
                created_utc: 1700000000,
              },
            },
          ],
        },
      }),
    };
  };

  try {
    const data = await briefing({
      env: { REDDIT_CLIENT_ID: 'client-id', REDDIT_CLIENT_SECRET: 'client-secret' },
      subreddits: ['worldnews'],
      delayMs: 0,
    });

    assert.equal(data.status, 'ok');
    assert.equal(data.subreddits.worldnews[0].title, 'Market stress headline');
    assert.ok(urls.some(url => url === 'https://www.reddit.com/api/v1/access_token'));
    assert.ok(urls.some(url => url.startsWith('https://oauth.reddit.com/r/worldnews/hot')));
    assert.equal(urls.some(url => url.includes('hot.json')), false);
  } finally {
    globalThis.fetch = originalFetch;
  }
});

test('Reddit config reports partial credential state', () => {
  assert.deepEqual(getRedditConfig({ REDDIT_CLIENT_ID: 'id' }).missing, ['REDDIT_CLIENT_SECRET']);
});
