/**
 * test/takedownWorker.test.js
 *
 * Regression coverage for worker paths that do not send mail.
 */

'use strict';

const assert = require('assert');
const { setupFreshDb, teardown } = require('./_setup');
const User = require('../models/user');
const Case = require('../models/case');
const Takedown = require('../models/takedown');
const { db } = require('../config/db');

function stubModule(modulePath, exports) {
  const resolved = require.resolve(modulePath);
  const previous = require.cache[resolved];
  require.cache[resolved] = {
    id: resolved,
    filename: resolved,
    loaded: true,
    exports,
  };
  return () => {
    if (previous) require.cache[resolved] = previous;
    else delete require.cache[resolved];
  };
}

function loadWorkerWithStubs(discoveryResult) {
  const restoreDiscovery = stubModule('../services/contactDiscovery', {
    discover: async () => discoveryResult,
  });
  const restoreRdap = stubModule('../services/rdap', {
    lookup: async () => null,
  });
  delete require.cache[require.resolve('../jobs/takedownWorker')];
  const worker = require('../jobs/takedownWorker');
  return {
    worker,
    restore() {
      delete require.cache[require.resolve('../jobs/takedownWorker')];
      restoreDiscovery();
      restoreRdap();
    },
  };
}

function makeUserAndCase() {
  const u = User.create({
    email: 'worker-' + Math.random().toString(36).slice(2, 10) + '@ncii.test',
    name: 'Worker Test',
    password: 'Password123!',
    plan: 'pro',
  });
  const c = Case.create({
    user_id: u.id,
    victim_name: 'Worker Victim',
    reference_url: 'https://reference.test',
    context: 'unit test',
  });
  return { userId: u.id, caseId: c.id };
}

const tests = [
  {
    name: 'takedown worker: no direct contact creates manual-required takedown and completes job',
    fn: async () => {
      setupFreshDb();
      const discoveryResult = {
        domain: 'no-contact.test',
        primary: null,
        secondary: [],
        form_url: null,
        security_txt: null,
        hosting: null,
        escalation_chain: [
          {
            step: 1,
            type: 'registrar',
            address: 'WHOIS-lookup: https://lookup.icann.org/en/lookup?q=no-contact.test',
            source: 'rfc7485',
            why: 'Registrar escalation required.',
          },
        ],
        errors: [],
      };
      const loaded = loadWorkerWithStubs(discoveryResult);
      try {
        const { userId, caseId } = makeUserAndCase();
        const jobId = Takedown.enqueueJob({
          case_id: caseId,
          user_id: userId,
          url: 'https://no-contact.test/leak',
          domain: 'no-contact.test',
        });
        const job = Takedown.getJob(jobId);

        const result = await loaded.worker.processJob(job);
        assert.strictEqual(result.action_required.type, 'escalate');

        const updatedJob = Takedown.getJob(jobId);
        assert.strictEqual(updatedJob.status, 'manual_required');
        assert.ok(updatedJob.takedown_id, 'job links to created takedown');
        assert.ok(updatedJob.escalation_json.includes('registrar'), 'job stores escalation chain');

        const td = db.prepare('SELECT * FROM takedowns WHERE id = ?').get(updatedJob.takedown_id);
        assert.strictEqual(td.status, 'manual-required');
        assert.strictEqual(td.contact_email, null);
        assert.ok(td.discovery_json.includes('no-contact.test'), 'takedown stores discovery payload');
        assert.ok(td.escalation_json.includes('registrar'), 'takedown stores escalation chain');
      } finally {
        loaded.restore();
        teardown();
      }
    },
  },
];

module.exports = tests;
