/**
 * test/dedup.test.js
 *
 * Verifies the model-level dedup at the Finding + Takedown layer:
 *  - Finding.create with the same (case_id, url) returns the existing row
 *    and sets __deduped: true
 *  - Takedown.create with the same (case_id, domain, contact_email) returns
 *    the existing row and sets __deduped: true
 *  - Takedown.create with a NULL contact_email dedups on (case_id, domain)
 *    (chain-only takedowns)
 *  - Different contact_emails on the same domain produce two distinct rows
 *    (we WANT one platform contact + one registrar contact for the same case)
 *
 * Exports an array of tests in the format expected by test/run.js.
 * Each test gets its own fresh in-memory DB via _setup.js helpers.
 */

'use strict';

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

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

const tests = [
  {
    name: 'Finding dedup: same (case_id, url) returns existing row + __deduped',
    fn: () => {
      setupFreshDb();
      try {
        const { userId, caseId } = makeUserAndCase();
        const a = Finding.create({ case_id: caseId, user_id: userId, url: 'https://example.com/leak-1', tier: 1, is_ncii: true, status: 'confirmed' });
        assert.ok(a.id > 0, 'first create returns an id');
        assert.strictEqual(a.__deduped, undefined, 'first create is NOT __deduped');
        const b = Finding.create({ case_id: caseId, user_id: userId, url: 'https://example.com/leak-1', tier: 1, is_ncii: true, status: 'confirmed' });
        assert.strictEqual(b.id, a.id, 'second create returns the SAME id');
        assert.strictEqual(b.__deduped, true, 'second create is __deduped');
      } finally { teardown(); }
    },
  },
  {
    name: 'Finding dedup: different url produces a new row',
    fn: () => {
      setupFreshDb();
      try {
        const { userId, caseId } = makeUserAndCase();
        const a = Finding.create({ case_id: caseId, user_id: userId, url: 'https://example.com/leak-1', tier: 1, is_ncii: true, status: 'confirmed' });
        const b = Finding.create({ case_id: caseId, user_id: userId, url: 'https://example.com/leak-2', tier: 1, is_ncii: true, status: 'confirmed' });
        assert.notStrictEqual(b.id, a.id, 'different URL produces a different row');
      } finally { teardown(); }
    },
  },
  {
    name: 'Takedown dedup: same (case, domain, contact) returns existing row',
    fn: () => {
      setupFreshDb();
      try {
        const { userId, caseId } = makeUserAndCase();
        const t1 = Takedown.create({ case_id: caseId, user_id: userId, url: 'https://example.com/leak-1', domain: 'example.com', contact_email: 'abuse@example.com', status: 'production_pending' });
        assert.ok(t1.id > 0, 'first takedown returns an id');
        assert.strictEqual(t1.__deduped, undefined, 'first is NOT __deduped');
        const t2 = Takedown.create({ case_id: caseId, user_id: userId, url: 'https://example.com/leak-1', domain: 'example.com', contact_email: 'abuse@example.com', status: 'production_pending' });
        assert.strictEqual(t2.id, t1.id, 'second (same recipient) returns the SAME id');
        assert.strictEqual(t2.__deduped, true, 'second is __deduped');
      } finally { teardown(); }
    },
  },
  {
    name: 'Takedown dedup: different recipient on same domain is allowed (platform + registrar)',
    fn: () => {
      setupFreshDb();
      try {
        const { userId, caseId } = makeUserAndCase();
        const t1 = Takedown.create({ case_id: caseId, user_id: userId, url: 'https://example.com/leak-1', domain: 'example.com', contact_email: 'abuse@example.com', status: 'production_pending' });
        const t2 = Takedown.create({ case_id: caseId, user_id: userId, url: 'https://example.com/leak-1', domain: 'example.com', contact_email: 'legal@example.com', status: 'production_pending' });
        assert.notStrictEqual(t2.id, t1.id, 'different recipient on same domain produces a NEW row');
      } finally { teardown(); }
    },
  },
  {
    name: 'Takedown dedup: chain-only (null contact) dedups on (case, domain) only',
    fn: () => {
      setupFreshDb();
      try {
        const { userId, caseId } = makeUserAndCase();
        const t1 = Takedown.create({ case_id: caseId, user_id: userId, url: 'https://other.com/', domain: 'other.com', contact_email: null, status: 'chain_only' });
        const t2 = Takedown.create({ case_id: caseId, user_id: userId, url: 'https://other.com/page2', domain: 'other.com', contact_email: null, status: 'chain_only' });
        assert.strictEqual(t2.id, t1.id, 'second chain-only (same domain) returns the SAME id');
        assert.strictEqual(t2.__deduped, true, 'second chain-only is __deduped');
      } finally { teardown(); }
    },
  },
  {
    name: 'Takedown dedup: null contact and real contact on same domain produce two distinct rows',
    fn: () => {
      setupFreshDb();
      try {
        const { userId, caseId } = makeUserAndCase();
        const t1 = Takedown.create({ case_id: caseId, user_id: userId, url: 'https://third.com/', domain: 'third.com', contact_email: 'dmca@third.com', status: 'production_pending' });
        const t2 = Takedown.create({ case_id: caseId, user_id: userId, url: 'https://third.com/', domain: 'third.com', contact_email: null, status: 'chain_only' });
        assert.notStrictEqual(t2.id, t1.id, 'null contact on same domain is a DIFFERENT row (chain-only vs contact)');
      } finally { teardown(); }
    },
  },
];

module.exports = tests;
