import type { SidecarCommand, SidecarEvent } from '../protocol';
import * as vncManager from './vnc-manager';
import { createSidecarConnector } from '../connect';
import { getOwnerHomeDir } from '@@/data-path';
import { API_URL } from '../../officer-url.mjs';

// ── 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 'vnc:start': {
      try {
        const { port, display } = await vncManager.startSession(cmd.params);
        reply({ type: 'vnc:started', id: cmd.id, port, display });
      } catch (err) {
        reply({ type: 'vnc:error', id: cmd.id, error: err instanceof Error ? err.message : String(err) });
      }
      break;
    }

    case 'vnc:ensure-password': {
      try {
        const { password } = await vncManager.ensureVncPassword(getOwnerHomeDir(cmd.email));
        reply({ type: 'vnc:password', id: cmd.id, password });
      } catch (err) {
        reply({ type: 'vnc:error', id: cmd.id, error: err instanceof Error ? err.message : String(err) });
      }
      break;
    }

    case 'vnc:stop':
      vncManager.stopSession(cmd.email);
      reply({ type: 'vnc:stopped', id: cmd.id });
      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: 'vnc',
  capabilities: ['vnc'],
  onCommand(cmd, reply) {
    handleCommand(cmd as SidecarCommand, reply as ReplyFn);
  },
});

// ── Graceful shutdown ──

function shutdown(signal: string) {
  console.log(`[vnc] ${signal} received, stopping all sessions...`);
  vncManager.stopAll();
  connection.destroy();
  process.exit(0);
}

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