import { readFileSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
import chalk from 'chalk';
import { logger } from '../../utils/logger.js';
import { analyzeRequestComplexity } from '../../lib/analysis/complexity-analyzer.js';
import { LearningSystem } from '../../lib/learning/learning-system.js';
import { loadStandardsForAgent, getStandardsListForAgent } from '../../lib/standards/standards-context-injector.js';
import { resolveAgentsConfigPath } from '../../lib/stacks/stack-resolver.js';

const __dirname = dirname(fileURLToPath(import.meta.url));
const frameworkRoot = join(__dirname, '..', '..', '..');

function loadAgentsConfig() {
  try {
    const configPath = resolveAgentsConfigPath(frameworkRoot);
    const content = readFileSync(configPath, 'utf8');
    return JSON.parse(content);
  } catch (err) {
    logger.error(`Failed to load agents config: ${err.message}`);
    process.exit(1);
  }
}

function detectAgents(userInput, config) {
  const input = userInput.toLowerCase();

  // MORPH 3.0 Hierarchical: agents is a flat object, not arrays
  const allAgents = Object.entries(config.agents || {})
    .filter(([id]) => !id.startsWith('_comment'))
    .map(([id, agent]) => ({ id, ...agent }));

  // Core agents = always_active agents (typically Tier 1)
  const coreAgents = allAgents.filter(a => a.always_active === true);
  const coreIds = coreAgents.map(a => a.id);

  // Specialist agents = keyword-matched agents
  const specialistMatches = [];

  for (const agent of allAgents) {
    if (agent.always_active) continue; // Skip core agents

    // MORPH 3.0.1: Check negative keywords first — if any match, skip agent entirely
    const negativeKeywords = agent.negativeKeywords || [];
    const hasNegativeMatch = negativeKeywords.some(neg =>
      input.includes(neg.toLowerCase())
    );
    if (hasNegativeMatch) continue;

    // MORPH 3.0: keywords is directly on agent, not nested in autoActivation
    const keywords = agent.keywords || [];
    const matchedKeywords = [];

    for (const keyword of keywords) {
      if (input.includes(keyword.toLowerCase())) {
        matchedKeywords.push(keyword);
      }
    }

    if (matchedKeywords.length > 0) {
      specialistMatches.push({
        id: agent.id,
        name: agent.title || agent.id, // Use title as name
        emoji: agent.teammate?.icon || '🤖',
        matchedKeywords,
        matchCount: matchedKeywords.length
      });
    }
  }

  specialistMatches.sort((a, b) => b.matchCount - a.matchCount);

  const specialistIds = specialistMatches.map(m => m.id);
  const allIds = [...new Set([...coreIds, ...specialistIds])];

  return {
    core: coreIds,
    specialists: specialistIds,
    all: allIds,
    matches: specialistMatches,
    input: userInput
  };
}

function formatVerbose(result) {
  logger.blank();
  logger.header('AGENT DETECTION RESULT');
  logger.info(`Input: ${chalk.white(result.input)}`);
  logger.blank();

  logger.header('CORE AGENTS (always active)');
  result.core.forEach(id => {
    logger.info(`  ${chalk.green('✓')} ${id}`);
  });
  logger.blank();

  if (result.matches.length > 0) {
    logger.header('SPECIALIST AGENTS (keyword matched)');
    result.matches.forEach(match => {
      logger.info(`  ${match.emoji} ${chalk.yellow(match.name)} (${match.matchCount} matches)`);
      logger.dim(`     Keywords: ${match.matchedKeywords.join(', ')}`);
    });
  } else {
    logger.dim('  No specialist agents matched');
  }

  logger.blank();
  logger.info(`Total: ${chalk.cyan(result.all.length)} agents activated`);
  logger.blank();
}

export { detectAgents, loadAgentsConfig };

export function detectAgentsCommand(input, options) {
  const userInput = Array.isArray(input) ? input.join(' ') : input;

  if (!userInput) {
    logger.error('User input is required');
    logger.dim('Usage: morph-spec detect-agents "your feature description"');
    process.exit(1);
  }

  const config = loadAgentsConfig();
  const result = detectAgents(userInput, config);

  // Stack-aware filtering: penalize stack-mismatched agents
  try {
    const projectConfigPath = join(process.cwd(), '.morph/config/config.json');
    const projectConfig = JSON.parse(readFileSync(projectConfigPath, 'utf8'));
    const stack = projectConfig?.project?.stack || projectConfig?.project?.language || '';
    const isJsStack = stack === 'nodejs' || stack === 'javascript' || stack === 'nextjs';

    if (isJsStack) {
      const dotnetKeywords = ['dotnet', '.net', 'csharp', 'c#', 'blazor', 'razor', 'azure', 'bicep',
        'ef core', 'entity framework', 'hangfire', 'mudblazor', 'fluent ui', 'asp.net'];
      const hasExplicitDotnetRequest = dotnetKeywords.some(k => userInput.toLowerCase().includes(k));

      if (!hasExplicitDotnetRequest) {
        const dotnetAgents = new Set([
          'dotnet-senior', 'azure-architect', 'ef-modeler', 'bicep-architect',
          'blazor-builder', 'blazor-concurrency-validator', 'hangfire-orchestrator',
          'azure-deploy-specialist'
        ]);
        result.core = result.core.filter(id => !dotnetAgents.has(id));
        result.specialists = result.specialists.filter(id => !dotnetAgents.has(id));
        result.all = result.all.filter(id => !dotnetAgents.has(id));
        result.matches = result.matches.filter(m => !dotnetAgents.has(m.id));
      }
    }
  } catch {
    // Config not found or unreadable — skip stack filtering
  }

  // Enrich with complexity analysis
  try {
    result.complexity = analyzeRequestComplexity(userInput);
    result.suggestedWorkflow = result.complexity.workflow;
  } catch {
    result.complexity = null;
    result.suggestedWorkflow = 'standard';
  }

  // Enrich with learning suggestions
  try {
    const learner = new LearningSystem('.');
    result.learningSuggestions = learner.getAllSuggestions();
  } catch {
    result.learningSuggestions = null;
  }

  // Enrich with skill paths for each detected agent
  const allAgents = Object.entries(config.agents || {})
    .filter(([id]) => !id.startsWith('_'))
    .map(([id, agent]) => ({ id, ...agent }));
  result.skillPaths = result.all
    .map(id => {
      const agent = allAgents.find(a => a.id === id);
      return agent?.skillPath || null;
    })
    .filter(Boolean);

  // Enrich with standards context when JSON output requested
  if (options.json) {
    const projectPath = process.cwd();
    result.standardsSummary = {};

    for (const agentId of result.all) {
      const standardsList = getStandardsListForAgent(agentId);
      const { fullContent } = loadStandardsForAgent(agentId, projectPath);

      result.standardsSummary[agentId] = {
        standards: standardsList,
        fullContent: fullContent,
        count: standardsList.length
      };
    }
  }

  if (options.json) {
    console.log(JSON.stringify(result, null, 2));
  } else if (options.verbose) {
    formatVerbose(result);
  } else if (options.idsOnly) {
    result.all.forEach(id => console.log(id));
  } else {
    console.log(JSON.stringify(result.all));
  }
}
