#!/usr/bin/env node

/**
 * RoutineCode Setup CLI
 *
 * Usage:
 *   npx @routinecrew/routinecode setup          # Full setup (MCP + hooks + plugin + API key)
 *   npx @routinecrew/routinecode status          # Show current config
 *   npx @routinecrew/routinecode install-deps   # Install MCP server dependencies
 *
 * Flow:
 *   1. routinecrew.com 회원가입 → tenantId + userId 자동 발행
 *   2. /get-api-key 에서 RoutineCode 서비스 API Key 발급
 *   3. routinecode setup → API Key 입력 → 자동 설정 완료
 */

import { readFileSync, writeFileSync, existsSync, mkdirSync, chmodSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
import { execSync } from 'child_process';
import { homedir } from 'os';
import { randomBytes } from 'crypto';
import { createInterface } from 'readline';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const PACKAGE_ROOT = join(__dirname, '..');
const CLAUDE_DIR = join(homedir(), '.claude');
const SETTINGS_PATH = join(CLAUDE_DIR, 'settings.json');
const RC_CONFIG_DIR = join(homedir(), '.routinecode');
const RC_CONFIG_PATH = join(RC_CONFIG_DIR, 'config.json');

const MCP_SERVERS = [
  'mcp-routinecode',
  'mcp-log-watcher',
  'mcp-intelligence',
  'mcp-project-context',
  'mcp-plan-manager',
  'mcp-doc-fetcher',
  'mcp-dev-tester',
  'mcp-db-manager',
  'mcp-html-renderer',
];

function ask(question) {
  const rl = createInterface({ input: process.stdin, output: process.stdout });
  return new Promise(resolve => {
    rl.question(question, answer => {
      rl.close();
      resolve(answer.trim());
    });
  });
}

function loadSettings() {
  if (!existsSync(SETTINGS_PATH)) {
    return {};
  }
  return JSON.parse(readFileSync(SETTINGS_PATH, 'utf-8'));
}

function saveSettings(settings) {
  if (!existsSync(CLAUDE_DIR)) mkdirSync(CLAUDE_DIR, { recursive: true });
  writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2) + '\n', 'utf-8');
}

function loadRcConfig() {
  if (!existsSync(RC_CONFIG_PATH)) {
    return {
      syncEnabled: false,
      machineId: randomBytes(8).toString('hex'),
    };
  }
  return JSON.parse(readFileSync(RC_CONFIG_PATH, 'utf-8'));
}

function saveRcConfig(config) {
  if (!existsSync(RC_CONFIG_DIR)) mkdirSync(RC_CONFIG_DIR, { recursive: true });
  writeFileSync(RC_CONFIG_PATH, JSON.stringify(config, null, 2) + '\n', 'utf-8');
}

// ============================================================
// Commands
// ============================================================

async function setupMcpServers() {
  console.log('\n[1/3] Registering MCP servers + permissions...\n');
  const settings = loadSettings();
  if (!settings.mcpServers) settings.mcpServers = {};

  // Permissions: bypassPermissions mode + explicit tool allow list
  settings.permissions = {
    defaultMode: 'bypassPermissions',
    allow: [
      'Bash',
      'Read',
      'Edit',
      'Write',
      'Glob',
      'Grep',
      'Agent',
      'WebFetch',
      'WebSearch',
      'mcp__*',
    ],
  };
  settings.skipDangerousModePermissionPrompt = true;

  for (const server of MCP_SERVERS) {
    // Prefer bundled .mjs, fallback to legacy .js
    const cjsPath = join(PACKAGE_ROOT, server, 'dist', 'index.cjs');
    const jsPath = join(PACKAGE_ROOT, server, 'dist', 'index.js');
    const distPath = existsSync(cjsPath) ? cjsPath : jsPath;
    if (!existsSync(distPath)) {
      console.log(`  SKIP  ${server} (not built)`);
      continue;
    }
    settings.mcpServers[server] = {
      command: 'node',
      args: [distPath],
    };

    console.log(`  OK    ${server}`);
  }

  saveSettings(settings);
  console.log(`\n  -> ${SETTINGS_PATH}`);
  console.log('  -> All tools auto-allowed (no permission prompts)');
}

function setupHooks() {
  console.log('\n[2/3] Registering hooks...\n');
  const settings = loadSettings();

  const hooksDir = join(PACKAGE_ROOT, 'hooks');

  // Ensure hook scripts are executable
  for (const script of ['session-start.sh', 'pre-edit-check.sh', 'post-build-check.sh']) {
    const scriptPath = join(hooksDir, script);
    if (existsSync(scriptPath)) {
      chmodSync(scriptPath, '755');
    }
  }

  settings.hooks = {
    SessionStart: [{
      matcher: '',
      hooks: [{
        type: 'command',
        command: join(hooksDir, 'session-start.sh'),
      }],
    }],
    PostToolUse: [{
      matcher: 'mcp__routinecode__build_check',
      hooks: [{
        type: 'command',
        command: join(hooksDir, 'post-build-check.sh'),
      }],
    }],
    PreToolUse: [{
      matcher: 'Edit',
      hooks: [{
        type: 'command',
        command: join(hooksDir, 'pre-edit-check.sh'),
      }],
    }],
  };

  saveSettings(settings);
  console.log('  OK    SessionStart  (escalation reset)');
  console.log('  OK    PostToolUse   (build failure -> knowledge query)');
  console.log('  OK    PreToolUse    (3-Strike edit block)');
}

function setupPlugin() {
  console.log('\n[3/3] Registering plugin...\n');
  const settings = loadSettings();

  if (!settings.enabledPlugins) settings.enabledPlugins = {};

  // Plugin path = package root's plugin/ directory
  const pluginDir = join(PACKAGE_ROOT, 'plugin');
  if (existsSync(join(pluginDir, 'routinecode-prompt.md'))) {
    settings.enabledPlugins['routinecode@local'] = true;
    console.log(`  OK    routinecode plugin`);
    console.log(`  PATH  ${pluginDir}`);
  } else {
    console.log('  SKIP  plugin directory not found');
  }

  saveSettings(settings);
}

async function activateApiKey() {
  console.log('\n[4/4] Activating intelligence sync...\n');

  const config = loadRcConfig();

  if (config.tenantId && config.apiKey) {
    console.log(`  Already activated: tenant=${config.tenantId}`);
    const reset = await ask('  Re-activate with a different key? (y/N): ');
    if (reset.toLowerCase() !== 'y') return;
  }

  console.log('  Get your API Key at: https://routinecrew.com/get-api-key');
  console.log('  1. Sign up or log in at routinecrew.com');
  console.log('  2. Select "RoutineCode" service');
  console.log('  3. Copy the API Key\n');

  const apiKey = await ask('  API Key: ');

  if (!apiKey) {
    console.log('\n  Skipped. Run `routinecode setup` again to activate later.');
    return;
  }

  const serverUrl = 'https://api.routinecrew.com';

  // Validate API Key against Auth server — key contains tenantId mapping
  console.log('\n  Validating...');
  try {
    const res = await fetch(`${serverUrl}/api/v1/api-keys/verify`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${apiKey}`,
      },
      signal: AbortSignal.timeout(10000),
    });

    if (res.ok) {
      const data = await res.json();
      config.tenantId = String(data.tenantId);
      config.userId = String(data.userId ?? data.createdBy ?? null);
      config.tenantCode = data.tenantCode ?? null;
      config.serverUrl = serverUrl;
      config.apiKey = apiKey;
      config.syncEnabled = true;
      saveRcConfig(config);
      console.log(`\n  Activated!`);
      console.log(`  Tenant:  ${config.tenantCode ?? config.tenantId}`);
      console.log(`  Sync:    enabled`);
      console.log('  Your development intelligence will sync to your account.');
    } else if (res.status === 401) {
      console.log('\n  Invalid API Key. Check your key at routinecrew.com/get-api-key');
    } else {
      // Server issue — save key, sync will activate when server is available
      config.serverUrl = serverUrl;
      config.apiKey = apiKey;
      config.syncEnabled = true;
      saveRcConfig(config);
      console.log(`\n  Server unavailable (${res.status}). Key saved.`);
      console.log('  Intelligence sync will activate automatically when connected.');
    }
  } catch {
    // Offline — save key for later
    config.serverUrl = serverUrl;
    config.apiKey = apiKey;
    config.syncEnabled = true;
    saveRcConfig(config);
    console.log('\n  Offline. Key saved.');
    console.log('  Intelligence sync will activate when connected.');
  }
}

function showStatus() {
  console.log('\n=== RoutineCode Status ===\n');

  // RC Config
  const config = loadRcConfig();
  console.log('Account:');
  console.log(`  tenantId:    ${config.tenantId ?? '(not activated)'}`);
  console.log(`  tenantCode:  ${config.tenantCode ?? '-'}`);
  console.log(`  userId:      ${config.userId ?? '-'}`);
  console.log(`  machineId:   ${config.machineId}`);
  console.log(`  syncEnabled: ${config.syncEnabled}`);
  console.log(`  serverUrl:   ${config.serverUrl ?? '(not set)'}`);

  // Knowledge files
  const knowledgeDir = join(RC_CONFIG_DIR, 'knowledge');
  console.log('\nKnowledge:');
  for (const file of ['events.jsonl', 'patterns.jsonl', 'quirks.jsonl']) {
    const p = join(knowledgeDir, file);
    if (existsSync(p)) {
      const lines = readFileSync(p, 'utf-8').trim().split('\n').filter(Boolean).length;
      console.log(`  ${file}: ${lines} entries`);
    } else {
      console.log(`  ${file}: (empty)`);
    }
  }

  // MCP Servers
  const settings = loadSettings();
  console.log('\nMCP Servers:');
  for (const server of MCP_SERVERS) {
    const registered = settings.mcpServers?.[server] ? 'ON' : 'OFF';
    console.log(`  ${registered}  ${server}`);
  }

  // Hooks
  console.log('\nHooks:');
  const hooks = settings.hooks;
  console.log(`  SessionStart: ${hooks?.SessionStart ? 'ON' : 'OFF'}`);
  console.log(`  PostToolUse:  ${hooks?.PostToolUse ? 'ON' : 'OFF'}`);
  console.log(`  PreToolUse:   ${hooks?.PreToolUse ? 'ON' : 'OFF'}`);

  // Permissions
  console.log('\nPermissions:');
  const allows = settings.permissions?.allow ?? [];
  const mcpAllows = allows.filter(a => a.startsWith('mcp__'));
  console.log(`  Auto-allowed: ${mcpAllows.length} MCP tool patterns`);
}

async function installDeps() {
  console.log('\nInstalling MCP server dependencies...\n');
  for (const server of MCP_SERVERS) {
    const serverDir = join(PACKAGE_ROOT, server);
    if (!existsSync(join(serverDir, 'package.json'))) {
      console.log(`  SKIP  ${server}`);
      continue;
    }
    console.log(`  ...   ${server}`);
    try {
      execSync('npm install --production --silent', { cwd: serverDir, stdio: 'pipe' });
      console.log(`  OK    ${server}`);
    } catch (e) {
      console.log(`  FAIL  ${server}: ${e.message}`);
    }
  }
}

// ============================================================
// Main
// ============================================================

const command = process.argv[2] || 'setup';

console.log('');
console.log('  RoutineCode v2.4.0');
console.log('  Claude Code Superset — 59 MCP Tools + Multi-Agent Orchestration');
console.log('  https://github.com/routinecrew/routinecode');
console.log('');

switch (command) {
  case 'setup': {
    await setupMcpServers();
    setupHooks();
    setupPlugin();
    await activateApiKey();
    console.log('\n=== Setup Complete ===');
    console.log('\nRestart Claude Code to activate RoutineCode.\n');
    break;
  }
  case 'status':
    showStatus();
    break;
  case 'install-deps':
    await installDeps();
    break;
  default:
    console.log(`Unknown command: ${command}`);
    console.log('\nUsage:');
    console.log('  routinecode setup          Full setup (MCP + hooks + plugin + API key)');
    console.log('  routinecode status         Show current configuration');
    console.log('  routinecode install-deps   Install MCP server dependencies');
    process.exit(1);
}
