// Credential-Form Signal Providers (v3)
// Typed features for overlay-credential (dt-overlay-credential-v3) and
// autofill-harvesting (dt-autofill-harvesting-v3). Ported from the dead
// detectors of the same names. They read the DOM-structure snapshot
// (target.dom.credentialOverlays / hiddenAutofillInputs) built by content.js.
//
// The load-bearing precision anchor for overlay-credential is CROSS-ORIGIN form
// submission: a legit login/re-auth modal posts to its own origin; an injected
// phishing overlay posts the password to the attacker. That distinction is what
// keeps this from firing on every site's normal login modal.

const SESSION_EXPIRED = [
  'session expired', 'session has expired', 'logged out', 'log in again',
  'sign in again', 'authentication required', 'verify your identity',
  'confirm your credentials', 're-authenticate', 'reauthenticate',
];
const URGENCY = [
  'urgent', 'immediate', 'act now', 'suspended', 'locked', 'unusual activity',
  'verify now', 'confirm immediately', 'unauthorized',
];
const TWOFA = [
  '2fa', 'two-factor', 'two factor', 'authentication code', 'verification code',
  'one-time password', 'one time password', 'enter the code', 'security code', 'otp',
];

function anyIncludes(text, list) {
  const t = (text || '').toLowerCase();
  return list.some(p => t.includes(p));
}

/**
 * @param {import('../../core/signal-provider.js').SignalProviderRegistry} registry
 */
export function registerCredentialFormSignals(registry) {
  // ── dt.cross_origin_credential ────────────────
  // A password/OTP field whose form submits to a different origin.
  registry.register('dt', 'cross_origin_credential', (target) => {
    const overlays = (target.dom && target.dom.credentialOverlays) || [];
    for (const o of overlays) {
      if ((o.hasPassword || o.hasOtp) && o.crossOrigin) {
        return { value: true, metadata: { hasPassword: o.hasPassword, hasOtp: o.hasOtp } };
      }
    }
    return { value: false };
  }, { returnType: 'boolean', scope: 'tab', description: 'Credential form submitting cross-origin' });

  // ── dt.fake_reauth_prompt ─────────────────────
  // A positioned credential overlay that posts cross-origin AND carries
  // re-auth / urgency / 2FA framing — a fake "session expired / verify" prompt.
  registry.register('dt', 'fake_reauth_prompt', (target) => {
    const overlays = (target.dom && target.dom.credentialOverlays) || [];
    for (const o of overlays) {
      if (!(o.hasPassword || o.hasOtp) || !o.crossOrigin || !o.positioned) continue;
      const reauth = anyIncludes(o.text, SESSION_EXPIRED) || anyIncludes(o.text, URGENCY);
      const twofa = o.hasOtp && anyIncludes(o.text, TWOFA);
      if (reauth || twofa) {
        return { value: true, metadata: { kind: twofa ? '2fa-harvest' : 'fake-reauth' } };
      }
    }
    return { value: false };
  }, { returnType: 'boolean', scope: 'tab', description: 'Cross-origin re-auth / 2FA harvesting overlay' });

  // ── dt.hidden_autofill_harvest ────────────────
  // An invisibly-rendered input with a sensitive (financial / password)
  // autocomplete attribute — harvesting the browser's autofill silently.
  registry.register('dt', 'hidden_autofill_harvest', (target) => {
    const hidden = (target.dom && target.dom.hiddenAutofillInputs) || [];
    if (hidden.length === 0) return { value: false };
    return { value: true, metadata: { count: hidden.length, fields: hidden.slice(0, 4).map(h => `${h.autocomplete}:${h.reason}`) } };
  }, { returnType: 'boolean', scope: 'tab', description: 'Hidden input harvesting sensitive autofill' });
}
