import { promisify } from 'util';
import { exec } from 'child_process';
import * as fs from 'fs/promises';
import { Action, ActionContext, ActionSchema, StandardTool, GenericToolSchema } from '../types/tool';

export class Tool<TInput = any, TOutput = any> implements Action<TInput, TOutput>, StandardTool {
  public name: string;
  public schema: ActionSchema<TInput, TOutput>;
  public code: string;
  public description: string;

  constructor(name: string, schema: ActionSchema<TInput, TOutput>, code: string, description: string) {
    this.name = name;
    this.schema = schema;
    this.code = code;
    this.description = description;
  }

  async execute(params: TInput, context: ActionContext): Promise<TOutput> {
    const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
    const asyncExecute = new AsyncFunction('params', 'context', 'util', 'exec', 'fs', `
      const execPromise = util.promisify(exec);
      ${this.code}
    `);
    return await asyncExecute(params, context, { promisify }, exec, fs) as TOutput;
  }

  getSchema(): GenericToolSchema {
    return {
      name: this.name,
      description: this.description,
      parameters: this.schema.input
    };
  }

  validate(args: Record<string, any>): boolean {
    // Implement validation logic here
    return true;
  }
}