import readline from 'node:readline';
import { GlmClient, Agent, buildTools, ApprovalManager } from '@naomi/core';
import { loadConfig, saveConfig, CONFIG_PATH } from './config.js';
import { startUiServer } from './local-server.js';

export async function runCli(argv) {
  const [command, ...rest] = argv;
  const flags = parseFlags(rest);

  switch (command) {
    case 'ui':
      return startUiServer({ port: Number(flags.port) || undefined });
    case 'chat':
      return runChat(flags);
    case 'config':
      return cmdConfig(flags);
    case 'admin':
      return cmdAdmin(rest);
    case 'help':
    case undefined:
      printHelp();
      return;
    default:
      printHelp();
      throw new Error(`неизвестная команда: ${command}`);
  }
}

function parseFlags(args) {
  const flags = {};
  const positional = [];
  for (let i = 0; i < args.length; i++) {
    if (args[i].startsWith('--')) {
      const key = args[i].slice(2);
      const next = args[i + 1];
      if (next && !next.startsWith('--')) {
        flags[key] = next;
        i++;
      } else {
        flags[key] = true;
      }
    } else {
      positional.push(args[i]);
    }
  }
  flags._ = positional;
  return flags;
}

function printHelp() {
  console.log(`
NAOMI Cloud — агент GLM на вашем ПК

  naomi ui                      веб-интерфейс (по умолчанию http://127.0.0.1:8420)
  naomi chat                    чат в терминале
  naomi config --server URL --key naomi_... [--model glm-4.6] [--policy safe|ask|auto]
  naomi admin --server URL --admin-key KEY <команда>
      keys                                  список ключей
      create-key <баланс> <метка>           выдать новый ключ (баланс в кредитах)
      topup <ключ> <сумма>                  пополнить
      block <ключ> | unblock <ключ>         блокировка
      usage                                 статистика заработка

Конфиг: ${CONFIG_PATH}
`);
}

async function cmdConfig(flags) {
  const patch = {};
  for (const field of ['server', 'apiKey', 'model', 'policy', 'uiPort']) {
    if (flags[field]) patch[field] = String(flags[field]);
  }
  if (flags.key) patch.apiKey = String(flags.key);
  const next = saveConfig(patch);
  console.log('Конфигурация:', { ...next, apiKey: next.apiKey ? `${next.apiKey.slice(0, 10)}...` : '' });
}

async function cmdAdmin(args) {
  const flags = parseFlags(args);
  const cfg = loadConfig();
  const server = (flags.server ?? cfg.server).replace(/\/+$/, '');
  const adminKey = flags['admin-key'];
  const [action, arg1, arg2] = flags._;
  if (!action) {
    printHelp();
    return;
  }

  const call = async (path, init = {}) => {
    const res = await fetch(`${server}${path}`, {
      ...init,
      headers: {
        'content-type': 'application/json',
        authorization: `Bearer ${adminKey}`,
        ...(init.headers ?? {}),
      },
      signal: AbortSignal.timeout(15000),
    });
    const json = await res.json().catch(() => ({}));
    if (!res.ok) throw new Error(json.error?.message ?? res.statusText);
    return json;
  };

  switch (action) {
    case 'keys': {
      const { keys } = await call('/admin/keys');
      console.table(keys.map((k) => ({
        key: k.key,
        label: k.label,
        balance: k.balance,
        blocked: k.blocked,
        spent_30d: k.spent_30d,
      })));
      return;
    }
    case 'create-key': {
      const balance = Number(arg1 ?? 0);
      const label = arg2 ?? '';
      const created = await call('/admin/keys', {
        method: 'POST',
        body: JSON.stringify({ balance, label }),
      });
      console.log(`Ключ выдан:\n  key: ${created.key}\n  label: ${created.label}\n  balance: ${created.balance}`);
      return;
    }
    case 'topup': {
      const result = await call(`/admin/keys/${arg1}/topup`, {
        method: 'POST',
        body: JSON.stringify({ amount: Number(arg2 ?? 0) }),
      });
      console.log('Пополнено:', result);
      return;
    }
    case 'block':
    case 'unblock': {
      const result = await call(`/admin/keys/${arg1}/${action}`, { method: 'POST', body: '{}' });
      console.log(action === 'block' ? 'Заблокирован:' : 'Разблокирован:', result);
      return;
    }
    case 'usage': {
      console.log(await call('/admin/usage'));
      return;
    }
    case 'topups': {
      const { topups } = await call(`/admin/topups${flags.all ? '' : '?status=pending'}`);
      if (!topups.length) { console.log(flags.all ? 'Заявок нет' : 'Новых заявок нет 🎉'); return; }
      console.table(topups.map((t) => ({
        id: t.id,
        amount: t.amount,
        method: t.method,
        status: t.status,
        label: t.label,
        key: `${t.key.slice(0, 12)}…`,
      })));
      return;
    }
    case 'topup-approve':
    case 'topup-reject': {
      const result = await call(`/admin/topups/${arg1}/${action === 'topup-approve' ? 'approve' : 'reject'}`, { method: 'POST', body: '{}' });
      console.log(action === 'topup-approve' ? `Пополнено на ${result.amount} ₡ (заявка #${result.id})` : `Заявка #${result.id} отклонена`);
      return;
    }
    default:
      printHelp();
      throw new Error(`неизвестное действие admin: ${action}`);
  }
}

async function runChat(flags) {
  const cfg = loadConfig();
  if (!cfg.apiKey) {
    throw new Error(`сначала: naomi config --server <URL> --key naomi_...`);
  }
  const approvals = new ApprovalManager();
  const tools = buildTools();
  const client = new GlmClient({
    baseUrl: `${cfg.server.replace(/\/+$/, '')}/v1`,
    apiKey: cfg.apiKey,
    model: flags.model ?? cfg.model,
  });
  const agent = new Agent({ client, tools, approvals, policy: flags.policy ?? cfg.policy });

  agent.on('delta', ({ chunk }) => {
    process.stdout.write(chunk);
  });
  agent.on('llm_start', () => {
    process.stdout.write('\x1b[2m');
  });
  agent.on('message_done', () => {
    process.stdout.write('\x1b[0m');
  });
  agent.on('tool_start', ({ name, args }) => {
    process.stdout.write(`\n\x1b[36m  ▸ ${name}: ${summarize(name, args)}\x1b[0m\n`);
  });
  agent.on('tool_end', ({ result }) => {
    const brief = result?.error
      ? `\x1b[31m${result.error}\x1b[0m`
      : `\x1b[2m${firstLines(result)}\x1b[0m`;
    process.stdout.write(`  ${brief}\n`);
  });

  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
  const ask = (q) => new Promise((resolve) => rl.question(q, resolve));

  approvals.on('approval', async (info) => {
    console.log(`\n\x1b[33m  ⚠ Требуется подтверждение: ${info.name} — ${info.reason}\x1b[0m`);
    const answer = (await ask('  Разрешить? [y/N/a(всегда)] ')).trim().toLowerCase();
    if (answer === 'a') agent.setPolicy('auto');
    approvals.resolve(info.id, answer === 'y' || answer === 'a' || answer === 'да');
  });

  console.log(`NAOMI чат · ${client.model} · ${cfg.server} · policy=${agent.policy}`);
  console.log('Команды: /exit выход, /reset новая сессия\n');

  while (true) {
    const text = await ask('\x1b[1mты ›\x1b[0m ');
    const trimmed = text.trim();
    if (!trimmed) continue;
    if (trimmed === '/exit') break;
    if (trimmed === '/reset') {
      agent.reset();
      console.log('\x1b[2m— новая сессия —\x1b[0m');
      continue;
    }
    process.stdout.write('\x1b[2mnaomi ›\x1b[0m ');
    try {
      await agent.run(trimmed);
    } catch (err) {
      console.error(`\x1b[31mОшибка: ${err.message}\x1b[0m`);
    }
    process.stdout.write('\n');
  }
  rl.close();
}

function summarize(name, args) {
  if (name === 'run_command') return args.command;
  if (name === 'write_file') return args.path;
  return JSON.stringify(args).slice(0, 100);
}

function firstLines(result) {
  const text = result?.stdout || result?.content || JSON.stringify(result ?? {});
  return text.split('\n').slice(0, 3).join(' ⏎ ').slice(0, 160);
}
