// Reddit social sentiment intelligence.
// Reddit API access requires OAuth. Runtime sweeps intentionally do not use
// unauthenticated reddit.com .json scraping because it is unreliable and not
// acceptable for production operation.

import { safeFetch } from '../utils/fetch.mjs';
import '../utils/env.mjs';

function delay(ms) { return new Promise(r => setTimeout(r, ms)); }

const USER_AGENT = 'Crucix/2.0 intelligence-engine';

const SUBREDDITS = [
  'worldnews',
  'geopolitics',
  'economics',
  'wallstreetbets',
  'commodities',
];

export function getRedditConfig(env = process.env) {
  const clientId = env.REDDIT_CLIENT_ID || '';
  const clientSecret = env.REDDIT_CLIENT_SECRET || '';
  const missing = [];
  if (!clientId) missing.push('REDDIT_CLIENT_ID');
  if (!clientSecret) missing.push('REDDIT_CLIENT_SECRET');
  return {
    clientId,
    clientSecret,
    configured: missing.length === 0,
    missing,
  };
}

function credentialsMessage(missing) {
  return `Reddit requires OAuth. Register a script app at https://www.reddit.com/prefs/apps/ and set ${missing.join(' and ')} in .env`;
}

export async function getToken({ env = process.env, fetchImpl = globalThis.fetch } = {}) {
  const config = getRedditConfig(env);
  if (!config.configured) {
    return {
      ok: false,
      status: 'no_credentials',
      missing: config.missing,
      error: 'missing_reddit_oauth_credentials',
      message: credentialsMessage(config.missing),
    };
  }

  try {
    const auth = Buffer.from(`${config.clientId}:${config.clientSecret}`).toString('base64');
    const res = await fetchImpl('https://www.reddit.com/api/v1/access_token', {
      method: 'POST',
      headers: {
        'Authorization': `Basic ${auth}`,
        'Content-Type': 'application/x-www-form-urlencoded',
        'User-Agent': USER_AGENT,
      },
      body: 'grant_type=client_credentials',
    });
    if (!res.ok) {
      const body = await res.text().catch(() => '');
      return {
        ok: false,
        status: 'auth_failed',
        error: `reddit_oauth_http_${res.status}`,
        message: `Reddit OAuth token request failed with HTTP ${res.status}`,
        detail: body.slice(0, 200),
      };
    }

    const data = await res.json();
    if (!data.access_token) {
      return {
        ok: false,
        status: 'auth_failed',
        error: 'reddit_oauth_missing_access_token',
        message: 'Reddit OAuth token response did not include an access token',
      };
    }
    return { ok: true, status: 'ok', token: data.access_token };
  } catch (e) {
    return {
      ok: false,
      status: 'auth_failed',
      error: 'reddit_oauth_request_failed',
      message: e.message,
    };
  }
}

export async function getHot(subreddit, opts = {}) {
  const { limit = 10, token = null } = opts;

  if (!token) {
    return {
      status: 'no_credentials',
      error: 'reddit_oauth_required',
      message: 'Reddit source requires OAuth; unauthenticated reddit.com .json scraping is disabled',
    };
  }

  return safeFetch(`https://oauth.reddit.com/r/${subreddit}/hot?limit=${limit}&raw_json=1`, {
    source: 'Reddit',
    headers: {
      'Authorization': `Bearer ${token}`,
      'User-Agent': USER_AGENT,
    },
  });
}

function compactPost(child) {
  const d = child?.data;
  if (!d) return null;
  return {
    title: d.title,
    score: d.score ?? 0,
    comments: d.num_comments ?? 0,
    url: d.url,
    created: d.created_utc ? new Date(d.created_utc * 1000).toISOString() : null,
  };
}

export async function briefing(opts = {}) {
  const {
    env = process.env,
    subreddits = SUBREDDITS,
    delayMs = 1000,
    fetchImpl = globalThis.fetch,
  } = opts;
  const tokenResult = await getToken({ env, fetchImpl });

  if (!tokenResult.ok) {
    return {
      source: 'Reddit',
      timestamp: new Date().toISOString(),
      status: tokenResult.status,
      error: tokenResult.error,
      message: tokenResult.message,
      missing: tokenResult.missing || [],
    };
  }

  const subredditResults = {};
  const errors = [];
  for (const sub of subreddits) {
    const result = await getHot(sub, { limit: 10, token: tokenResult.token });
    if (result?.error) {
      errors.push({ subreddit: sub, error: result.error });
      subredditResults[sub] = [];
      if (delayMs > 0) await delay(delayMs);
      continue;
    }
    const children = result?.data?.children || [];
    subredditResults[sub] = children.map(compactPost).filter(Boolean);
    if (delayMs > 0) await delay(delayMs);
  }

  return {
    source: 'Reddit',
    timestamp: new Date().toISOString(),
    status: errors.length > 0 ? 'degraded' : 'ok',
    ...(errors.length > 0 ? { error: 'reddit_subreddit_fetch_failed', errors } : {}),
    subreddits: subredditResults,
  };
}

if (process.argv[1]?.endsWith('reddit.mjs')) {
  const data = await briefing();
  console.log(JSON.stringify(data, null, 2));
}
