import { spawn } from 'child_process';

import { AgentEngine, EngineRunInput, EngineRunResult } from './types.js';

const DEFAULT_PI_TUI_BIN = 'pi';
const DEFAULT_PI_SESSION_DIR = '/home/node/.agent/pi';
const PI_SESSION_SENTINEL = 'pi-session';

export class PiTuiEngine implements AgentEngine {
  readonly name = 'pi-tui';

  async runTurn(input: EngineRunInput): Promise<EngineRunResult> {
    if (input.shouldClose()) {
      input.log('Close sentinel detected before pi-tui turn started');
      return { closedDuringTurn: true };
    }

    const binary = process.env.PI_TUI_BIN || DEFAULT_PI_TUI_BIN;
    const args = this.buildArgs(input);

    input.log(`Starting pi-tui turn with ${binary}`);

    const result = await new Promise<string>((resolve, reject) => {
      const proc = spawn(binary, args, {
        cwd: '/workspace/group',
        env: {
          ...process.env,
          ...input.sdkEnv,
          PI_CODING_AGENT_DIR:
            process.env.PI_CODING_AGENT_DIR || DEFAULT_PI_SESSION_DIR,
          PI_TUI_GROUP_FOLDER: input.jailInput.groupFolder,
          PI_TUI_CHAT_JID: input.jailInput.chatJid,
          PI_TUI_IS_MAIN: input.jailInput.isMain ? '1' : '0',
        },
        stdio: ['ignore', 'pipe', 'pipe'],
      });

      let stdout = '';
      let stderr = '';

      proc.stdout.on('data', (chunk) => {
        stdout += chunk.toString();
      });

      proc.stderr.on('data', (chunk) => {
        stderr += chunk.toString();
      });

      proc.on('error', (err) => {
        reject(err);
      });

      proc.on('close', (code) => {
        if (code === 0) {
          resolve(stdout.trim());
          return;
        }
        reject(
          new Error(
            `${binary} exited with code ${code}: ${stderr.trim() || 'no stderr'}`,
          ),
        );
      });
    });

    const sessionId = input.sessionId || PI_SESSION_SENTINEL;

    input.emitOutput({
      status: 'success',
      result,
      newSessionId: sessionId,
    });

    return {
      newSessionId: sessionId,
      lastAssistantUuid: input.resumeAt,
      closedDuringTurn: false,
    };
  }

  private buildArgs(input: EngineRunInput): string[] {
    const args = ['-p', '--mode', 'text'];
    const provider = process.env.PI_TUI_PROVIDER;
    if (provider) {
      args.push('--provider', provider);
    }
    const model = process.env.PI_TUI_MODEL;
    if (model) {
      args.push('--model', model);
    }
    if (input.sessionId) {
      args.push('--continue');
    }
    args.push(
      '--session-dir',
      process.env.PI_CODING_AGENT_DIR || DEFAULT_PI_SESSION_DIR,
    );
    if (input.jailInput.assistantName) {
      args.push(
        '--append-system-prompt',
        `Assistant name: ${input.jailInput.assistantName}`,
      );
    }
    args.push(input.prompt);
    return args;
  }
}
