'use strict';

/**
 * services/indexnow.js — IndexNow submission for instant Bing/Yandex indexing.
 *
 * submitAll()      — fetches live blog slugs + submits all public URLs.
 *                    Called once on startup (production only) and after blog seeding.
 * submitUrls(urls) — submit an explicit list of absolute URLs immediately.
 *                    Called from any route that creates or updates a public page.
 *
 * Key hosted at: https://tunevault.app/fb2d470871584f71b75727bfbb1777cc.txt
 * Registered with: Bing Webmaster Tools
 */

const https = require('https');
const { listSlugs } = require('../db/blog');

const SITE_URL  = 'https://tunevault.app';
const KEY       = 'fb2d470871584f71b75727bfbb1777cc';
const KEY_URL   = `${SITE_URL}/${KEY}.txt`;
const ENDPOINT  = 'https://api.indexnow.org/IndexNow';

// Static public pages — mirrors STATIC_PAGES in routes/seo.js (excluding noindex pages).
// Keep in sync when new public routes are added.
const STATIC_PATHS = [
  '/',
  '/pricing',
  '/vs-oem',
  '/compare',
  '/features',
  '/sample-report',
  '/request-health-check',
  '/blog',
  '/features/sql-tuning',
  '/features/fleet-management',
  '/features/autonomous-remediation',
  '/about',
  '/trust',
  '/security',
  '/architecture',
  '/docs',
  '/sql-tuning',
  '/docs/oracle-setup',
  '/api-docs',
  '/resources/runbooks',
  '/resources/runbooks/tablespace-full-recovery',
  '/resources/runbooks/archive-log-destination-full',
  '/resources/runbooks/opp-tuning-ebs',
  '/resources/runbooks/workflow-mailer-smtp-recovery',
  '/resources/runbooks/adop-cutover-rollback',
  '/resources/runbooks/oracle-db-upgrade-triage',
  '/resources/runbooks/ebs-upgrade-triage',
  '/resources/runbooks/agent-connection-failure',
  '/llms.txt',
  '/login',
  '/privacy',
  '/terms',
];

// Per-process flag — resets on each deploy/restart so startup always runs once.
let startupSubmitted = false;

/**
 * POST a URL batch to IndexNow.
 * @param {string[]} urlList — absolute URLs (https://tunevault.app/...)
 */
async function submitUrls(urlList) {
  if (!urlList || urlList.length === 0) return;

  const body = JSON.stringify({
    host:        'tunevault.app',
    key:         KEY,
    keyLocation: KEY_URL,
    urlList,
  });

  return new Promise((resolve, reject) => {
    const url = new URL(ENDPOINT);
    const req = https.request({
      hostname: url.hostname,
      path:     url.pathname,
      method:   'POST',
      headers: {
        'Content-Type':   'application/json; charset=utf-8',
        'Content-Length': Buffer.byteLength(body),
      },
    }, res => {
      let data = '';
      res.on('data', chunk => { data += chunk; });
      res.on('end', () => {
        if (res.statusCode >= 200 && res.statusCode < 300) {
          console.log(`[indexnow] submitted ${urlList.length} URLs — HTTP ${res.statusCode}`);
          resolve();
        } else {
          // 422 = URL already known (not an error), 429 = rate-limited
          console.warn(`[indexnow] HTTP ${res.statusCode}: ${data.slice(0, 200)}`);
          resolve(); // non-fatal
        }
      });
    });
    req.on('error', err => {
      console.warn('[indexnow] request error:', err.message);
      resolve(); // non-fatal
    });
    req.setTimeout(10000, () => {
      req.destroy();
      console.warn('[indexnow] request timed out');
      resolve(); // non-fatal
    });
    req.write(body);
    req.end();
  });
}

/**
 * Build the full URL list: static pages + live blog slugs from DB.
 * Non-fatal if DB is unavailable — static pages are still submitted.
 */
async function buildAllUrls() {
  const urls = STATIC_PATHS.map(p => `${SITE_URL}${p}`);

  try {
    const slugs = await listSlugs();
    for (const { slug } of slugs) {
      urls.push(`${SITE_URL}/blog/${slug}`);
    }
  } catch (err) {
    console.warn('[indexnow] could not fetch blog slugs:', err.message);
  }

  return urls;
}

/**
 * Submit all public URLs to IndexNow. Called on startup + after blog seeding.
 * Uses a per-process flag on startup path to run only once per deploy.
 * @param {{ force?: boolean }} opts — pass { force: true } to bypass the startup flag (e.g. after seeding)
 */
async function submitAll({ force = false } = {}) {
  if (!force && startupSubmitted) return;
  startupSubmitted = true;

  const urls = await buildAllUrls();
  await submitUrls(urls);
}

module.exports = { submitAll, submitUrls, KEY, KEY_URL };
