import type { SidecarCommand, SidecarEvent } from '../protocol';
import { loadState, flushAndSave, acquireLock, releaseLock, getState } from './state';
import { startAnthropicProxy, getProxySecret, ensureProxySecret } from './proxy';
import { createSidecarConnector } from '../connect';
import { API_URL } from '../../officer-url.mjs';

// ── Startup ──

if (!acquireLock()) {
  console.error('[proxy] another instance is already running (lock file exists with live PID)');
  process.exit(1);
}

loadState();
ensureProxySecret();

// Start Anthropic proxy
try {
  startAnthropicProxy();
} catch (err) {
  console.error('[proxy] failed to start Anthropic proxy:', err instanceof Error ? err.message : err);
}

// ── Command handlers ──

type ReplyFn = (msg: SidecarEvent) => void;

async function handleCommand(cmd: SidecarCommand, reply: ReplyFn) {
  switch (cmd.type) {
    case 'ping':
      reply({ type: 'pong', id: cmd.id });
      break;

    case 'state:sync':
      reply({
        type: 'state:sync',
        id: cmd.id,
        state: {
          proxySecret: getProxySecret(),
          claudeSessions: { ...getState().claudeSessions },
        },
      });
      break;

    case 'proxy:secret':
      reply({ type: 'proxy:secret', id: cmd.id, secret: getProxySecret() });
      break;

    default:
      reply({
        type: 'error',
        id: (cmd as SidecarCommand).id,
        error: `Unknown command type: ${(cmd as Record<string, unknown>).type}`,
      });
  }
}

// ── Connect to API server ──

const connection = createSidecarConnector({
  apiUrl: `${API_URL}/api/sidecar/register`,
  name: 'proxy',
  capabilities: ['proxy'],
  onCommand(cmd, reply) {
    handleCommand(cmd as SidecarCommand, reply as ReplyFn);
  },
});

// ── Graceful shutdown ──

async function shutdown(signal: string) {
  console.log(`[proxy] ${signal} received, saving state...`);
  connection.destroy();
  await flushAndSave();
  releaseLock();
  process.exit(0);
}

process.on('SIGTERM', () => shutdown('SIGTERM'));
process.on('SIGINT', () => shutdown('SIGINT'));
