'use strict';

/**
 * Lightweight keyword/regex topic classifier.
 * No Claude call — pure pattern matching for fast context selection.
 */

const TOPIC_PATTERNS = {
  people: {
    // Names of known people, relationship words
    keywords: ['who', 'person', 'team', 'report', 'manager', 'colleague', 'relationship', 'trust'],
    regex: /\b(who\s+is|reports?\s+to|works?\s+with|relationship|team\s+member|direct\s+report|skip.?level)\b/i,
  },
  slack: {
    keywords: ['slack', 'channel', 'message', 'dm', 'thread', 'mention', 'said', 'told', 'wrote', 'posted'],
    regex: /\b(slack|channel|message[sd]?|DM|thread|mention|said|told|wrote|posted|conversation)\b|(?:^|[\s(])#\w+/i,
  },
  calendar: {
    keywords: ['calendar', 'meeting', 'schedule', 'tomorrow', 'appointment', '1:1', 'standup'],
    regex: /\b(calendar|meeting|schedule|tomorrow|tonight|this\s+week|next\s+(week|monday|tuesday|wednesday|thursday|friday|saturday|sunday)|appointment|1[:-]1|standup|sync|deadline|calendar\s+event)\b|(?:free|busy|available|availability)\s+(?:at|on|for)\s|(?:am\s+i\s+free|do\s+i\s+have\s+(?:any\s+)?meet)|会议|日程|明天/i,
  },
  tasks: {
    keywords: ['task', 'todo', 'reminder', 'deadline', 'priority', 'action item', 'backlog'],
    regex: /\b(tasks?|todo|to.?do|remind(er)?|deadlines?|priority|action\s+items?|backlog|sprint|jira|tickets?)\b|提醒|任务|待办/i,
  },
  technical: {
    keywords: ['code', 'bug', 'deploy', 'api', 'database', 'server', 'git', 'pr', 'test'],
    regex: /\b(code|code\s+review|review\s+(?:(?:local|uncommitted|unstaged|staged|working\s+tree|workspace)\s+)?(?:diff|patch|changes?|pr|pull\s+request)|(?:check|show|run)\s+git\s+status|bug|deploy|api|database|server|git|pr|pull\s+request|test|build|pipeline|docker|kubernetes|aws|gcp)\b/i,
  },
  tools: {
    keywords: ['tool', 'mcp', 'skill', 'fetch', 'execute', 'automation', 'disk', 'storage'],
    regex: /\b(tool|mcp|skill|fetch|search\s+for|run\s+(a|this|the|ls|my)|execute|automation|script|command|shell|install|open\s+(file|app|folder|terminal|browser|url)|disk\s*space|storage|system\s+info|file[s]?|folder[s]?|directory|delete\s+(all|my|the))\b|(?:^|\s)[~\/]\S+\.\w{1,10}\b|(?:^|\s)\/\w+\/\w+/i,
  },
  skills: {
    keywords: ['skill', 'claude code', 'codex', 'gemini', 'cursor', 'install', 'capability'],
    regex: /\b(skill|claude\s+code|codex|gemini\s+cli|cursor|install|capability|ctm-dev|frontend|browser.?test|publish)\b/i,
  },
  email: {
    keywords: ['email', 'mail', 'inbox', 'sent mail', 'unread'],
    regex: /\b(emails?|e-mail|mail|inbox|unread\s+messages?|sent\s+mail|from\s+\w+\s+about)\b|邮件|收件箱/i,
  },
  weather: {
    keywords: ['weather', 'wheather', 'wether', 'temperature', 'rain', 'snow', 'forecast', 'outside'],
    regex: /\b(weather|wheather|wether|how'?s\s+(?:the\s+)?whether|whether\s+(?:today|tomorrow|outside)|temperature|rain|snow|forecast|outside|humid|cold|hot|warm|sunny|cloudy)\b|天气|气温|下[雨雪]|预报/i,
  },
  location: {
    keywords: ['location', 'nearby', 'near me', 'local', 'physically'],
    regex: /\b(where\s+am\s+i|what\s+city\s+am\s+i\s+in|which\s+city\s+am\s+i\s+in|current\s+location|my\s+location|near\s+me|nearby|around\s+me|local\s+(weather|places?|restaurants?|coffee|time)|physically\s+(am\s+i|located)|location)\b|我在哪|附近/i,
  },
  personal: {
    keywords: ['feel', 'think about', 'opinion', 'preference', 'dislike', 'hobby', 'family'],
    regex: /\b(how\s+do\s+you\s+feel|opinion|preference|dislike|hobby|family|personal|habit|routine|favorite)\b/i,
  },
  work: {
    keywords: ['project', 'okr', 'goal', 'strategy', 'roadmap', 'planning', 'quarterly', 'perf'],
    regex: /\b(projects?|okrs?|goals?|strategy|roadmap|planning|quarterly|perf|review|promotion|career|leadership)\b/i,
  },
  finance: {
    keywords: ['finance', 'payment', 'invoice', 'budget', 'salary', 'tax', 'expense', 'revenue'],
    regex: /\b(financ\w*|payments?|invoic\w*|budget|salary|tax\w*|expenses?|revenue|billing)\b/i,
  },
  health: {
    keywords: ['health', 'fitness', 'workout', 'exercise', 'sleep', 'medical', 'doctor'],
    regex: /\b(health|fitness|workout|exercise|sleep|nutrition|medical|doctor)\b|健康|运动|睡眠/i,
  },
  hiring: {
    keywords: ['hire', 'hiring', 'interview', 'candidate', 'recruit', 'resume', 'onboarding'],
    regex: /\b(hir\w+|interview|candidates?|recruit\w*|resume|onboard\w*)\b/i,
  },
};

/**
 * Classify a user message into topic tags.
 * Returns array of matching topic names, e.g. ['people', 'slack'].
 * Always returns at least ['general'] if no specific match.
 */
function classifyTopics(message) {
  if (!message || typeof message !== 'string') return ['general'];

  const topics = [];
  const lower = message.toLowerCase();

  for (const [topic, { keywords, regex }] of Object.entries(TOPIC_PATTERNS)) {
    if (regex.test(message)) {
      topics.push(topic);
      continue;
    }
    // Fallback: check if any keyword appears as a whole word
    // (word boundary match to avoid false positives like "brain" matching "rain")
    if (keywords.some(kw => new RegExp('\\b' + kw.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '\\b', 'i').test(lower))) {
      topics.push(topic);
    }
  }

  // Check for people names — only if we don't already have people topic
  // Require 2+ capitalized words (first+last name) to avoid false positives on "Hi", "Walle", etc.
  if (!topics.includes('people') && /\b[A-Z][a-z]{2,}\s+[A-Z][a-z]{2,}\b/.test(message)) {
    topics.push('people');
  }

  return topics.length > 0 ? topics : ['general'];
}

/**
 * Map classified topics to an intent category that drives prompt assembly.
 * Returns one of: 'direct_action', 'knowledge', 'conversational'
 */
function classifyIntent(topics) {
  const DIRECT_ACTION_TOPICS = new Set(['calendar', 'weather', 'location', 'email']);
  const KNOWLEDGE_TOPICS = new Set(['people', 'work', 'slack', 'personal', 'finance', 'health', 'hiring']);

  const ACTION_TOPICS = new Set(['tools', 'skills', 'tasks']);
  const hasDirect = topics.some(t => DIRECT_ACTION_TOPICS.has(t));
  const hasAction = topics.some(t => ACTION_TOPICS.has(t));
  const hasKnowledge = topics.some(t => KNOWLEDGE_TOPICS.has(t));

  // Action topics (tasks, tools, skills) take priority — they're always about doing something
  if (hasAction) return 'direct_action';

  // Technical requests need tool/codebase handling more than memory search. This
  // must run before "work" because phrases like "code review" also match work
  // review/perf vocabulary.
  if (topics.includes('technical')) return 'direct_action';

  // City names such as "San Francisco" look like person names to the cheap
  // capitalized-name detector. For pure weather questions, keep direct-action
  // routing so the agent uses weather tools instead of memory search.
  if (hasDirect && topics.includes('weather') && topics.every(t => t === 'weather' || t === 'people')) {
    return 'direct_action';
  }

  // Knowledge topics get higher timeout/turns — if both knowledge AND direct topics
  // are present, prefer knowledge (memory search is slow, needs more time)
  if (hasKnowledge) return 'knowledge';
  if (hasDirect) return 'direct_action';

  // 'general' only → conversational
  if (topics.length === 1 && topics[0] === 'general') return 'conversational';

  return 'knowledge'; // default: treat as knowledge query
}

module.exports = { classifyTopics, classifyIntent, TOPIC_PATTERNS };
