#!/usr/bin/env raku
use v6.d;

use WWW::OpenAI;
use JSON::Fast;

my %*SUB-MAIN-OPTS =
        :named-anywhere,
        # allow named variables at any location
        ;

#| Finding textual answers using the OpenAI API.
multi sub openai-front(Str $text,                                #= Text to be questioned.
                       Str $questions,                           #= Questions separated with '?' or ';'.
                       UInt :mt(:$max-tokens) = 300,             #= The maximum number of tokens to generate in the completion.
                       Str :m(:$model) is copy = 'Whatever',     #= Model.
                       Real :t(:$temperature) = 0.7,             #= Temperature.
                       Str :r(:$request) = 'Whatever',           #= Request.
                       Bool :p(:$pairs) = False,                 #= Should question-answer pairs be returned or not?
                       Str :a(:$auth-key) is copy = 'Whatever',  #= Authorization key (to use OpenAI API.)
                       UInt :$timeout = 10,                      #= Timeout.
                       Bool :$echo = False,                      #= Should the query, result, answer be echoed or not?
                       Str :f(:$format) is copy = 'values',      #= Format of the result; one of "json", "hash", "values", or "Whatever".
                       Str :$method is copy = 'tiny',            #= Method for the HTTP POST query; one of "tiny" or "curl".
                       ) {

    if $text.chars == 0 {
        note 'Nothing.';
        return;
    }

    if $auth-key eq 'Whatever' {
        if %*ENV<OPENAI_API_KEY>:exists {
            $auth-key = %*ENV<OPENAI_API_KEY>;
        } else {
            note 'Cannot find OpenAI authorization key. ' ~
                    'Please provide a valid key to the argument auth-key, or set the ENV variable OPENAI_API_KEY.';
            $auth-key = ''
        }
    }

    if $format.lc ∈ <v auto whatever> { $format = 'values'; }

    my $res =
            openai-find-textual-answer($text,
                    $questions.split(/ <?after '?'> | ';' /, :skip-empty)>>.trim,
                    model => $model eq 'Whatever' ?? Whatever !! $model,
                    :$request,
                    :$pairs,
                    :$max-tokens,
                    :$temperature,
                    :$auth-key,
                    :$timeout,
                    :$echo,
                    :$format,
                    :$method);

    given $format.lc {
        when $_ ∈ <hash raku> { say $res.raku; }
        when $_ ∈ <json> { say to-json($res); }
        default { say $res; }
    }
}

multi sub MAIN
#= Command given as a sequence of words.
(*@words,
 Str :q($questions)!,                      #= Questions separated with '?' or ';'.
 UInt :mt(:$max-tokens) = 300,             #= The maximum number of tokens to generate in the completion.
 Str :m(:$model) is copy = 'Whatever',     #= Model.
 Real :t(:$temperature) = 0.7,             #= Temperature.
 Str :r(:$request) = 'Whatever',           #= Request.
 Bool :p(:$pairs) = False,                 #= Should question-answer pairs be returned or not?
 Str :a(:$auth-key) is copy = 'Whatever',  #= Authorization key (to use OpenAI API.)
 UInt :$timeout = 10,                      #= Timeout.
 Bool :$echo = False,                      #= Should the query, result, answer be echoed or not?
 Str :f(:$format) is copy = 'values',      #= Format of the result; one of "json", "hash", "values", or "Whatever".
 Str :$method is copy = 'tiny',            #= Method for the HTTP POST query; one of "tiny" or "curl".
 ) {
    return openai-front(@words.join(' ').Str, $questions, :$model, :$max-tokens, :$temperature, :$request, :$pairs, :$auth-key, :$timeout, :$echo, :$format, :$method);
}