'use strict';

const { createCodexAppServerClient } = require('./codex-app-server-client');

let client = null;
let currentSpec = null;
let nextParentRequestId = 1;
const pendingParentRequests = new Map();

function send(message) {
  if (typeof process.send === 'function') {
    process.send(message);
  }
}

function serializeError(err) {
  return {
    code: err?.code || -32603,
    message: err?.message || String(err || 'Codex App worker error'),
    data: err?.data || null,
  };
}

function reply(id, result, error) {
  if (!id) return;
  if (error) {
    send({ id, error: serializeError(error) });
  } else {
    send({ id, result: result || {} });
  }
}

function requestParent(request, timeoutMs = 300000) {
  const requestId = String(nextParentRequestId++);
  return new Promise((resolve, reject) => {
    const timer = setTimeout(() => {
      pendingParentRequests.delete(requestId);
      reject(new Error(`Codex App worker 等待主进程处理请求超时: ${request.method || ''}`));
    }, timeoutMs);
    pendingParentRequests.set(requestId, { resolve, reject, timer });
    send({ type: 'serverRequest', requestId, request });
  });
}

async function postInitialize({ request, onLog } = {}) {
  if (typeof request !== 'function') return;
  try {
    await request('experimentalFeature/enablement/set', { enablement: { goals: true } }, 30000);
    if (typeof onLog === 'function') onLog('INFO', 'codex_app_worker_goals_feature_enabled', {});
  } catch (err) {
    if (typeof onLog === 'function') {
      onLog('INFO', 'codex_app_worker_goals_feature_enable_failed', { error: err?.message || String(err || '') });
    }
  }

  try {
    const result = await request('collaborationMode/list', {}, 30000);
    if (typeof onLog === 'function') onLog('INFO', 'codex_app_worker_collaboration_modes', { result });
  } catch (err) {
    if (typeof onLog === 'function') {
      onLog('INFO', 'codex_app_worker_collaboration_mode_list_failed', { error: err?.message || String(err || '') });
    }
  }
}

function configure(spec = {}) {
  const nextSpec = {
    command: spec.command || 'codex',
    args: Array.isArray(spec.args) && spec.args.length > 0 ? spec.args : ['app-server', '--stdio'],
    env: spec.env || process.env,
    cwd: spec.cwd || process.cwd(),
    clientInfo: spec.clientInfo || undefined,
  };

  const nextSignature = JSON.stringify({
    command: nextSpec.command,
    args: nextSpec.args,
    cwd: nextSpec.cwd,
    envCodeHome: nextSpec.env.CODEX_HOME || '',
  });
  const currentSignature = currentSpec ? JSON.stringify({
    command: currentSpec.command,
    args: currentSpec.args,
    cwd: currentSpec.cwd,
    envCodeHome: currentSpec.env.CODEX_HOME || '',
  }) : '';

  if (client && nextSignature === currentSignature) {
    currentSpec = nextSpec;
    return;
  }

  if (client) {
    try { client.stop(); } catch {}
    client = null;
  }
  currentSpec = nextSpec;
  client = createCodexAppServerClient({
    command: nextSpec.command,
    args: nextSpec.args,
    env: nextSpec.env,
    cwd: nextSpec.cwd,
    clientInfo: nextSpec.clientInfo,
    onNotification: (notification) => send({ type: 'notification', notification }),
    onServerRequest: (request) => requestParent(request),
    onExit: (info) => send({ type: 'exit', info }),
    onLog: (level, event, data) => send({ type: 'log', level, event, data }),
    postInitialize,
  });
}

process.on('message', (message = {}) => {
  if (message.type === 'serverRequestResult') {
    const item = pendingParentRequests.get(String(message.requestId || ''));
    if (!item) return;
    pendingParentRequests.delete(String(message.requestId || ''));
    clearTimeout(item.timer);
    if (message.error) {
      const err = new Error(message.error.message || '主进程处理 Codex App 请求失败。');
      err.code = message.error.code;
      err.data = message.error.data;
      item.reject(err);
    } else {
      item.resolve(message.result || {});
    }
    return;
  }

  Promise.resolve()
    .then(async () => {
      switch (message.type) {
        case 'configure':
          configure(message.spec || {});
          return {};
        case 'start':
          if (!client) configure(currentSpec || {});
          return client.start();
        case 'request':
          if (!client) configure(currentSpec || {});
          return client.request(message.method, message.params || {}, message.timeoutMs || 300000);
        case 'notification':
          if (!client) configure(currentSpec || {});
          client.notification(message.method, message.params || {});
          return {};
        case 'reloadMcpServers':
          if (!client) configure(currentSpec || {});
          return client.reloadMcpServers();
        case 'stop':
          if (client) client.stop();
          process.exit(0);
          return {};
        default:
          throw new Error(`未知 Codex App worker 消息: ${message.type}`);
      }
    })
    .then((result) => reply(message.id, result))
    .catch((err) => reply(message.id, null, err));
});

process.on('disconnect', () => {
  if (client) {
    try { client.stop(); } catch {}
  }
  process.exit(0);
});
