import { Hono } from 'hono';
import { serveStatic } from 'hono/bun';
import { spawn } from 'bun';
import fs from 'fs';

// Configuration
const MODES_DIR = '/home/admin/Job-Info-Prod';
const MODE_CONFIG_FILE = `${MODES_DIR}/ModeSwitch/activeMode.txt`;
const SHARED_PORT = 3000;
const ORCHESTRATOR_PORT = 3001;

// Mode folder mappings
const MODE_FOLDERS: Record<string, string> = {
  'Mode1Test': 'Mode1Test',
  'Mode2Test': 'Mode2Test',
  'Mode3Test': 'Mode3Test',
  'Mode6Test': 'Mode6Test',
};

let currentMode: string = 'Mode1Test';
let currentProcess: any = null;

// Helper: Read active mode from config file
function readActiveMode(): string {
  try {
    if (fs.existsSync(MODE_CONFIG_FILE)) {
      const content = fs.readFileSync(MODE_CONFIG_FILE, 'utf-8').trim();
      return content || 'Test1Mode';
    }
  } catch (err) {
    console.error('Failed to read mode config:', err);
  }
  return 'Mode1Test';
}

// Helper: Write active mode to config file
function writeActiveMode(mode: string): void {
  try {
    fs.writeFileSync(MODE_CONFIG_FILE, mode, 'utf-8');
  } catch (err) {
    console.error('Failed to write mode config:', err);
  }
}

// Helper: Kill process on shared port
async function killProcessOnPort(port: number): Promise<void> {
  try {
    await Bun.spawn({
      cmd: ['pkill', '-f', `bun.*:${port}`],
      stdout: 'ignore',
      stderr: 'ignore',
    });
    // Fallback: Try to kill any Bun process we spawned
    if (currentProcess) {
      currentProcess.kill();
      currentProcess = null;
    }
    // Give OS time to release the port
    await new Promise(resolve => setTimeout(resolve, 500));
  } catch (err) {
    console.error(`Failed to kill process on port ${port}:`, err);
  }
}

// Helper: Start a mode
async function startMode(mode: string): Promise<boolean> {
  try {
    // Kill any existing process
    await killProcessOnPort(SHARED_PORT);

    const folderName = MODE_FOLDERS[mode];
    if (!folderName) {
      console.error(`Unknown mode: ${mode}`);
      return false;
    }

    const modePath = `${MODES_DIR}/${folderName}`;
    if (!fs.existsSync(modePath)) {
      console.error(`Mode folder not found: ${modePath}`);
      return false;
    }

    console.log(`[ModeSwitch] Starting ${mode} (${folderName}/) on port ${SHARED_PORT}...`);

    // Determine server path based on mode
    // Mode2Test uses AuthAndToken/backend/server.ts
    // Mode1Test and Mode3Test use backend/server.ts
    let serverPath = 'backend/server.ts';
    if (mode === 'Mode2Test') {
      serverPath = 'AuthAndToken/backend/server.ts';
    }

    // Start the mode's backend server
    currentProcess = Bun.spawn({
      cmd: [process.execPath, 'run', serverPath],
      cwd: modePath,
      env: {
        // Force mode service to bind to shared port
        PORT: String(SHARED_PORT),
      },
      stdout: 'pipe',
      stderr: 'pipe',
    });

    currentMode = mode;
    writeActiveMode(mode);

    // Read and log output from the spawned process
    if (currentProcess.stdout) {
      (async () => {
        const reader = currentProcess.stdout.getReader();
        while (true) {
          const { done, value } = await reader.read();
          if (done) break;
          console.log(`[${mode}]`, new TextDecoder().decode(value));
        }
      })();
    }

    console.log(`✓ ${mode} started successfully on port ${SHARED_PORT}`);
    return true;
  } catch (err) {
    console.error(`Failed to start ${mode}:`, err);
    return false;
  }
}

// Initialize app
const app = new Hono();

// Startup message
console.log(`
================================================================================
[ModeSwitch Orchestrator]
================================================================================
Listening on port: ${ORCHESTRATOR_PORT}
Shared mode port: ${SHARED_PORT}
Config file: ${MODE_CONFIG_FILE}
================================================================================
`);

// Start initial mode
const initialMode = readActiveMode();
await startMode(initialMode);

// Export for Bun
export default {
  port: ORCHESTRATOR_PORT,
  fetch: app.fetch,
};
