/**
 * Sandbox Command Router Middleware
 * Intercepts REST API commands when no relay is connected,
 * routing them to the sandbox service instead.
 */

import { sandboxClient } from '../sandbox.js';

/**
 * Middleware that routes file/git/exec commands to sandbox when no relay.
 * Used on routes that normally proxy to the relay (file ops, git, etc.)
 *
 * Usage: app.use('/api/sandbox-proxy', authenticateToken, sandboxCommandRouter);
 */
export function sandboxCommandRouter(req, res, next) {
  // If relay is connected, let the normal relay flow handle it
  if (req.hasRelay && req.hasRelay()) {
    return next();
  }

  // No relay — check if sandbox is available
  handleSandboxCommand(req, res).catch(() => {
    res.status(503).json({ error: 'No machine connected and sandbox unavailable' });
  });
}

async function handleSandboxCommand(req, res) {
  const userId = req.user.id;
  const { action, ...params } = req.body;

  // Verify sandbox is available
  const available = await sandboxClient.isAvailable();
  if (!available) {
    return res.status(503).json({ error: 'No machine connected and sandbox service unreachable' });
  }

  // Check if user has an active sandbox
  const status = await sandboxClient.getStatus(userId);
  if (!status.exists) {
    // Auto-init sandbox for the user
    await sandboxClient.initSandbox(userId);
  }

  // Route based on action
  switch (action) {
    case 'file-read': {
      const result = await sandboxClient.readFile(userId, params.filePath);
      return res.json(result);
    }
    case 'file-write': {
      const result = await sandboxClient.writeFile(userId, params.filePath, params.content);
      return res.json(result);
    }
    case 'file-tree': {
      const result = await sandboxClient.getFileTree(userId, params.dirPath, params.depth);
      return res.json(result);
    }
    case 'exec': {
      const result = await sandboxClient.exec(userId, params.command, {
        cwd: params.cwd,
        timeout: params.timeout,
        userKeys: params.userKeys,
      });
      return res.json(result);
    }
    case 'git': {
      const result = await sandboxClient.gitOperation(userId, params.gitCommand, params.cwd);
      return res.json(result);
    }
    default:
      return res.status(400).json({ error: `Unknown sandbox action: ${action}` });
  }
}

/**
 * WebSocket sandbox bridge — used in the WS handler for routing
 * claude-command/shell-command/file-* when no relay is connected.
 *
 * @param {string} userId
 * @param {string} messageType - WS message type (e.g. 'claude-command')
 * @param {object} data - WS message data
 * @param {object} writer - WebSocketWriter for sending responses
 * @returns {boolean} true if handled by sandbox, false if not
 */
export async function handleSandboxWebSocketCommand(userId, messageType, data, writer) {
  const available = await sandboxClient.isAvailable();
  if (!available) return false;

  try {
    // Ensure sandbox exists
    const status = await sandboxClient.getStatus(userId);
    if (!status.exists) {
      await sandboxClient.initSandbox(userId);
    }

    switch (messageType) {
      case 'claude-command': {
        // Execute claude CLI command in sandbox
        writer.send({ type: 'session-created', sessionId: data.sessionId || `sandbox-${Date.now()}` });
        writer.send({ type: 'stream', content: '[Sandbox] Executing in cloud sandbox...\n' });

        const result = await sandboxClient.exec(userId, `claude --print "${data.command}"`, {
          cwd: data.cwd,
          timeout: 120000,
          userKeys: data.userKeys,
        });

        writer.send({
          type: 'stream',
          content: result.stdout || '',
        });

        if (result.stderr) {
          writer.send({ type: 'stream', content: `\n${result.stderr}` });
        }

        writer.send({
          type: 'session-complete',
          sessionId: data.sessionId,
          exitCode: result.exitCode,
        });

        return true;
      }

      case 'shell-command': {
        const result = await sandboxClient.exec(userId, data.command, {
          cwd: data.cwd,
          timeout: data.timeout || 30000,
        });
        writer.send({
          type: 'shell-output',
          stdout: result.stdout,
          stderr: result.stderr,
          exitCode: result.exitCode,
        });
        return true;
      }

      case 'file-read': {
        const result = await sandboxClient.readFile(userId, data.filePath);
        writer.send({ type: 'file-content', ...result });
        return true;
      }

      case 'file-write': {
        const result = await sandboxClient.writeFile(userId, data.filePath, data.content);
        writer.send({ type: 'file-written', ...result });
        return true;
      }

      case 'file-tree': {
        const result = await sandboxClient.getFileTree(userId, data.dirPath, data.depth);
        writer.send({ type: 'file-tree', ...result });
        return true;
      }

      case 'git-operation': {
        const result = await sandboxClient.gitOperation(userId, data.gitCommand, data.cwd);
        writer.send({ type: 'git-result', ...result });
        return true;
      }

      default:
        return false;
    }
  } catch (error) {
    writer.send({
      type: 'error',
      error: `Sandbox error: ${error.message || 'Unknown error'}`,
    });
    return true; // Handled (with error)
  }
}
