/**
 * Micro Agent Factory — Create ultra-specialized agents
 *
 * Micro-agents are stripped-down versions of base agents with:
 * - Only the standards they need (1-3 files max)
 * - A single focused mission
 * - Minimal context overhead (~2-5K tokens vs 20-50K for full agent)
 *
 * Saved to: .morph/micro-agents/{name}.json
 */

import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync } from 'fs';
import { join } from 'path';

const MICRO_AGENTS_DIR = join(process.cwd(), '.morph/micro-agents');
const AGENTS_CONFIG = join(process.cwd(), '.morph/config/agents.json');

// ============================================================================
// Agent Creation
// ============================================================================

/**
 * Create a micro-agent from a base agent with a standards subset
 * @param {Object} opts
 * @param {string} opts.name - Micro-agent name (e.g., 'jwt-validator')
 * @param {string} opts.baseAgent - Base agent ID (e.g., 'security-expert')
 * @param {string[]} opts.standards - Relevant standards file paths (1-3 files)
 * @param {string} opts.mission - Focused mission description
 * @param {string[]} [opts.tools] - Tools this micro-agent uses (default: minimal set)
 * @param {Object} [opts.constraints] - Additional constraints
 * @returns {Object} Micro-agent config object
 */
export function createMicroAgent({ name, baseAgent, standards, mission, tools = null, constraints = {} }) {
  if (!name || !baseAgent || !mission) {
    throw new Error('name, baseAgent, and mission are required');
  }

  if (standards && standards.length > 5) {
    throw new Error('Micro-agents should load at most 5 standards files (ideally 1-3)');
  }

  const baseAgentConfig = loadBaseAgent(baseAgent);

  const microAgent = {
    id: name,
    type: 'micro-agent',
    baseAgent,
    createdAt: new Date().toISOString(),
    mission,
    tier: (baseAgentConfig?.tier || 3) + 1, // micro-agents are tier+1 (more specialized)
    domain: baseAgentConfig?.domain || 'general',
    standards: standards || [],
    tools: tools || ['Read', 'Write', 'Edit'],
    constraints: {
      maxStandards: 3,
      maxFiles: 10,
      focusOnly: mission,
      ...constraints
    },
    contextEstimate: {
      standards: (standards || []).length * 2000,
      overhead: 1500,
      total: ((standards || []).length * 2000) + 1500
    },
    prompt: generateMicroAgentPrompt({ name, baseAgent, standards, mission, constraints, baseAgentConfig })
  };

  return microAgent;
}

/**
 * Save a micro-agent to disk
 * @param {Object} microAgent - Micro-agent config (from createMicroAgent)
 * @returns {string} Path to saved file
 */
export function saveMicroAgent(microAgent) {
  if (!existsSync(MICRO_AGENTS_DIR)) {
    mkdirSync(MICRO_AGENTS_DIR, { recursive: true });
  }

  const filePath = join(MICRO_AGENTS_DIR, `${microAgent.id}.json`);
  writeFileSync(filePath, JSON.stringify(microAgent, null, 2), 'utf8');
  return filePath;
}

/**
 * List all micro-agents
 * @returns {Array} Array of micro-agent summaries
 */
export function listMicroAgents() {
  if (!existsSync(MICRO_AGENTS_DIR)) return [];

  return readdirSync(MICRO_AGENTS_DIR)
    .filter(f => f.endsWith('.json'))
    .map(f => {
      try {
        const agent = JSON.parse(readFileSync(join(MICRO_AGENTS_DIR, f), 'utf8'));
        return {
          id: agent.id,
          baseAgent: agent.baseAgent,
          mission: agent.mission,
          standards: agent.standards?.length || 0,
          contextEstimate: agent.contextEstimate?.total || 0,
          createdAt: agent.createdAt
        };
      } catch {
        return null;
      }
    })
    .filter(Boolean);
}

/**
 * Get a specific micro-agent
 * @param {string} name - Micro-agent name
 * @returns {Object|null} Micro-agent config or null
 */
export function getMicroAgent(name) {
  const filePath = join(MICRO_AGENTS_DIR, `${name}.json`);
  if (!existsSync(filePath)) return null;
  try {
    return JSON.parse(readFileSync(filePath, 'utf8'));
  } catch {
    return null;
  }
}

// ============================================================================
// Helpers
// ============================================================================

function loadBaseAgent(agentId) {
  if (!existsSync(AGENTS_CONFIG)) return null;
  try {
    const config = JSON.parse(readFileSync(AGENTS_CONFIG, 'utf8'));
    return config.agents?.find(a => a.id === agentId) || null;
  } catch {
    return null;
  }
}

function generateMicroAgentPrompt({ name, baseAgent, standards, mission, constraints, baseAgentConfig }) {
  const standardsList = standards?.map(s => `- framework/standards/${s}`).join('\n') || '(none)';

  return `You are a MICRO-AGENT: ${name}
Base: ${baseAgent} (${baseAgentConfig?.description || 'specialist'})

MISSION (single focus):
${mission}

STANDARDS TO LOAD (${standards?.length || 0} files):
${standardsList}

CONSTRAINTS:
- Focus ONLY on your mission above
- Do NOT load additional standards or context
- Maximum ${constraints.maxFiles || 10} files to read/write
- Report completion when done — do NOT start new tasks

This is a minimal-context agent. Stay focused.`;
}
