# frozen_string_literal: true

require "mini_racer"
require "json"

module DiscourseAi
  module AiBot
    module Tools
      class JavascriptEvaluator < Tool
        TIMEOUT = 500
        MAX_MEMORY = 10_000_000
        MARSHAL_STACK_DEPTH = 20

        def self.signature
          {
            name: name,
            description: "Evaluates JavaScript code using MiniRacer",
            parameters: [
              {
                name: "script",
                description: "The JavaScript code to evaluate",
                type: "string",
                required: true,
              },
            ],
          }
        end

        def self.name
          "javascript_evaluator"
        end

        def script
          parameters[:script].to_s
        end

        def timeout
          @timeout || TIMEOUT
        end

        def timeout=(value)
          @timeout = value
        end

        def max_memory
          @max_memory || MAX_MEMORY
        end

        def max_memory=(value)
          @max_memory = value
        end

        def invoke
          context =
            MiniRacer::Context.new(
              timeout: timeout,
              max_memory: MAX_MEMORY,
              marshal_stack_depth: MARSHAL_STACK_DEPTH,
            )

          # works around llms like anthropic loving console.log
          eval_script = <<~JS
            let console = {};
            console.log = function(val) {
              return val;
            };

            #{script}
          JS

          result = context.eval(eval_script)

          # only do special handling and truncating for long strings
          if result.to_s.length > 1000
            result = truncate(result.to_s, max_length: 10_000, percent_length: 0.3, llm: llm)
          end

          { result: result }
        rescue MiniRacer::ScriptTerminatedError => e
          { error: "JavaScript execution timed out: #{e.message}" }
        rescue MiniRacer::V8OutOfMemoryError => e
          { error: "JavaScript execution exceeded memory limit: #{e.message}" }
        rescue MiniRacer::Error => e
          { error: "JavaScript execution error: #{e.message}" }
        end

        def details
          <<~MD


            ```
            #{script}
            ```

          MD
        end

        private

        def description_args
          { script: script }
        end
      end
    end
  end
end
