'use strict';

/**
 * User Signals — implicit feedback detection from follow-up messages.
 *
 * After Wall-E responds, the user's next message carries implicit quality
 * signals. This module detects them via keyword/pattern matching and returns
 * a score adjustment. Signals are noisy per-instance but average out over
 * dozens of evaluations.
 */

const SIGNAL_PATTERNS = [
  {
    type: 'code-committed',
    pattern: /\b(committed|pushed|merged|shipped|deployed)\b/i,
    impact: 0.15,
  },
  {
    type: 'positive',
    pattern: /\b(thanks|thank you|great|perfect|excellent|awesome|exactly|nicely done|well done|good job)\b/i,
    impact: 0.1,
  },
  {
    type: 'new-task',
    pattern: /\b(now (do|create|build|make|write)|can you also|next,? (do|create|build))\b/i,
    impact: 0.1,
  },
  {
    type: 'correction',
    pattern: /^(no[,. ]|wrong|incorrect|that'?s not|i meant|actually,? (i|the|it))/i,
    impact: -0.2,
  },
  // 'rephrase' is handled specially (word-overlap heuristic)
  {
    type: 'follow-up-build',
    pattern: /\b(what about|how about|and also|additionally|one more thing)\b/i,
    impact: 0.05,
  },
  {
    type: 'code-review',
    pattern: /\b(review|check|look at|examine).{0,20}\b(code|output|result|implementation)\b/i,
    impact: 0.03,
  },
  // 'topic-change' is the catch-all at the end
];

const POSITIVE_PATTERN = SIGNAL_PATTERNS.find(s => s.type === 'positive').pattern;

/**
 * Tokenize text into lowercase words >= 3 chars.
 */
function tokenize(text) {
  return text.toLowerCase().split(/\W+/).filter(w => w.length >= 3);
}

/**
 * Compute fraction of text1's words that appear in text2.
 */
function computeWordOverlap(text1, text2) {
  const words1 = tokenize(text1);
  const words2 = new Set(tokenize(text2));
  if (words1.length === 0) return 0;
  const matches = words1.filter(w => words2.has(w)).length;
  return matches / words1.length;
}

/**
 * Detect an implicit signal from a follow-up message.
 *
 * @param {string} followUpMessage — user's next message after Wall-E responded
 * @param {string} originalMessage — the original question Wall-E answered
 * @returns {{ type: string, impact: number } | null}
 */
function detectSignal(followUpMessage, originalMessage) {
  if (!followUpMessage || followUpMessage.trim().length < 3) return null;

  // Check patterns in priority order (first match wins)
  for (const { type, pattern, impact } of SIGNAL_PATTERNS) {
    if (pattern.test(followUpMessage)) {
      return { type, impact };
    }
  }

  // Rephrase detection: high overlap + question + no positive signal
  const overlap = computeWordOverlap(originalMessage, followUpMessage);
  if (
    overlap > 0.4 &&
    followUpMessage.includes('?') &&
    !POSITIVE_PATTERN.test(followUpMessage)
  ) {
    return { type: 'rephrase', impact: -0.15 };
  }

  // Topic-change: low overlap catch-all
  if (overlap <= 0.4) {
    return { type: 'topic-change', impact: 0.05 };
  }

  return null;
}

/**
 * Apply a signal's impact to a current score, clamped to [0, 1].
 */
function applySignalToScore(currentScore, signal) {
  return Math.max(0, Math.min(1, +(currentScore + signal.impact).toFixed(10)));
}

module.exports = { detectSignal, applySignalToScore, computeWordOverlap };
