# shellcheck shell=dash disable=2120,3028
# @gemini "summary data [ddgo:x-cmd jq]() and [wiki:x-cmd jq]()"

# @gemini --ddgo "keyword"
# @gemini + ddgo "keyword"
# @gemini + wp "keyword"
# @gemini - wp

xrc:mod:lib     chat        exec/util exec/history  exec/ted exec/repl exec/repl_id

# ___X_CMD_CHAT_CURRENT_ATTCHMENT=
# ___X_CMD_CHAT_CURRENT_SESSION=

___x_cmd_chat___exec(){
    local ___X_CMD_CHAT_CURRENT_ATTCHMENT="$___X_CMD_CHAT_CURRENT_ATTCHMENT"
    local ___X_CMD_CHAT_CURRENT_SESSION="$___X_CMD_CHAT_CURRENT_SESSION"
    local ___X_CMD_CHAT_CURRENT_HISTORY_MAX="$___X_CMD_CHAT_CURRENT_HISTORY_MAX"

    local IFS=" "

    local question=""
    local history=""
    local minion=""
    local session=""
    local hist_session=""
    local model=""
    local system=""
    local type="chat"
    local confirm_before_send=""
    # local question_op=""
    local count_token=""
    local filelist_attach=""
    local provider="gemini"
    local numbered=""
    local temperature=""
    local maxtoken=""
    local history_num=""
    local repl_history_num=""
    local seed=""

    local inputtype=""
    [ -n "$NO_PIPE_DATA_SIGN_DISPLAY" ] || local inputdesc="This data form pipe"

    local NL="${___X_CMD_UNSEENCHAR_NEWLINE}"
    local reflist=""

    local cache_time=1h
    local is_silent=""
    local modellist=""
    local is_no_empty_question=""
    local is_start_with_repl=""
    local is_end_with_repl=""
    local is_interactive=""

    local is_reasoning=""
    local is_stream=""
    local is_debug=""
    local is_enactnone=""

    if ___x_cmd_is_stdout2tty && ___x_cmd_runmode_allow_chatty; then
        is_end_with_repl=1
    fi

    local x_=""
    while [ $# -gt 0 ]; do
        case "$1" in
            --provider)     provider="$2";
                            [ $# -ge 2 ] || N=chat M="Please provide the provider value" log:ret:64;
                            ___x_cmd_chat_provider___validate "$provider" || return $?
                            shift 2 ;;

            -t|--temperature)
                            temperature="$2"
                            [ $# -ge 2 ] || N=chat M="Please provide the temperature value" log:ret:64;
                            shift 2
                            ;;
            --seed)         seed="$2"
                            [ $# -ge 2 ] || N=chat M="Please provide the seed value" log:ret:64;
                            shift 2
                            ;;
            --maxtoken)     maxtoken="$2"
                            [ $# -ge 2 ] || N=chat M="Please provide the maximum token length for the response" log:ret:64;
                            shift 2
                            ;;

            --jina)         [ $# -ge 2 ] || N=chat M="Please provide the URL value" log:ret:64;
                            x_=; ___x_cmd_chat___exec_jina_ "$2" || return $?
                            reflist="${reflist}${x_}${NL}"
                            shift 2 ;;

            ## DDGO just preserve the top 10 results
            --ddgo)         [ $# -ge 2 ] || N=chat M="Please provide the duckduckgo keyword" log:ret:64;
                            x_=; ___x_cmd_chat___exec_ddgo_ "$2" || return $?
                            reflist="${reflist}${x_}${NL}"
                            shift 2 ;;
            --tldr)         [ $# -ge 2 ] || N=chat M="Please provide the tldr command" log:ret:64;
                            x_=; ___x_cmd_chat___exec_tldr_ "$2" || return $?
                            reflist="${reflist}${x_}${NL}"
                            shift 2 ;;

            # --ddgq)         ;;
            # --wp)           ;; # wikipedia
            # --cht)          ;;

            --kv)           [ $# -ge 3 ] || N=chat M="Please provide the key-value, --kv <key> <value>" log:ret:64
                            x_=; ___x_cmd_chat___exec_kv_ "$2" "$3" || return $?
                            reflist="${reflist}${x_}${NL}"
                            shift 3 ;;
            # --eval "x ls # list all files"
            --eval)
                            [ $# -ge 2 ] || N=chat M="Please provide the command to eval" log:ret:64;
                            chat:info "Eval command -> $2"
                            x_=; ___x_cmd_chat___exec_cmd_ "$2" "Result from execute $2" || return $?
                            reflist="${reflist}${x_}${NL}"
                            shift 2 ;;

            -e)             [ $# -ge 2 ] || N=chat M="Please provide the env name" log:ret:64;
                            x_=; ___x_cmd_chat___exec_env_ "$2" || return $?
                            reflist="${reflist}${x_}${NL}"
                            shift 2 ;;
            -f|--file)
                            [ $# -ge 2 ] || N=chat M="Please provide the filepath" log:ret:64;
                            if ___x_cmd_chat___exec_filelist_ "$2" "$numbered"; then
                                filelist_attach="${filelist_attach}${x_}${NL}"
                            else
                                return 1
                            fi
                            shift 2 ;;

            -s|--session)
                            session="$2";
                            [ $# -ge 2 ] || N=chat M="Please provide the session value" log:ret:64; shift 2
                            case "$session" in
                                -|--)
                                    x_=; ___x_cmd_chat___exec_repl___id_previous_ || ___x_cmd_chat___exec_repl___id_previous_app_ || return $?
                                    session="$x_"
                                ;;
                            esac
                            ;;
            --hist-session) hist_session="$2";      [ $# -ge 2 ] || N=chat M="Please provide the history session value" log:ret:64; shift 2 ;;
            --minion)       minion="$2";            [ $# -ge 2 ] || N=chat M="Please provide the minion value"  log:ret:64; shift 2 ;;
            --history|-n)   history_num="$2";       [ $# -ge 2 ] || N=chat M="Please provide the history num"   log:ret:64; shift 2 ;;
            --model)        if [ $# -ge 2 ]; then
                                model="$2"; shift 2; continue
                            elif ___x_cmd_runmode_allow_chatty ; then
                                modellist="$( ___x_cmd_chat_model_ls "$provider" )" || return $?
                                [ -n "$modellist" ] || return $?
                                model="$( ___x_cmd pick --ask "Select the model value" <<A
$modellist
A
)" || return $?
                                shift
                            fi

                            [ -n "$model" ] || N=chat M="Please provide the model value" log:ret:64
                            ;;
            --system)       system="$2";            [ $# -ge 2 ] || N=chat M="Please provide the system value"  log:ret:64; shift 2 ;;
            # --context)
            --type)         type="$2";              [ $# -ge 2 ] || N=chat M="Please provide the type value"    log:ret:64; shift 2 ;;
            --count)        count_token=1 ;         shift 1 ;; # now just gemini kimi

            -c)             confirm_before_send=1;  shift 1 ;;

            # --edit)         inputtype="${1#--}";    shift 1 ;;

            -P|--nopipe)    inputtype=none;         shift 1 ;;      # For script process if inside the pipe
            -p|--pipe)      inputtype=pipe;
                            inputdesc="$2"
                            [ $# -ge 2 ] || N=chat M="Please provide a description of the value of the input pipe" log:ret:64;
                            shift 2 ;;

            --numbered)     numbered=1;             shift 1 ;;
            --silent)       is_silent=1;            shift 1 ;;

            # deprecated ...
            --question)     question="$2";          [ $# -ge 2 ] || N=chat M="Please provide the question value" log:ret:64;  shift 2 ;;
            --reasoning)    is_reasoning=1;         shift 1 ;;
            --no-reasoning) is_reasoning=0;         shift 1 ;;
            --stream)       is_stream=1;            shift 1 ;;
            --no-stream)    is_stream=0;            shift 1 ;;
            --debug)        is_debug=1;             shift 1 ;;
            --help|-h)
                            case "$provider" in
                                gh) ___x_cmd help -m gh model chat request      ;;
                                *)  ___x_cmd help -m "$provider" chat request   ;;
                            esac
                            return
                            ;;
            --no-empty-question)
                            is_no_empty_question=1; shift 1 ;;
            --start-with-repl)
                            is_start_with_repl=1;   shift 1 ;;
            --end-with-repl)
                            is_end_with_repl=1;     shift 1 ;;
            --start-without-repl)
                            is_start_with_repl="";  shift 1 ;;
            --end-without-repl)
                            is_end_with_repl="";    shift 1 ;;
            --without-repl)
                            is_start_with_repl=""; is_end_with_repl=""; shift 1 ;;
            --interactive)      is_interactive=1;   shift 1 ;;
            --non-interactive)  is_interactive=0;   shift 1 ;;
            --enactnone)        is_enactnone=1;     shift 1
                                is_stream=0; is_start_with_repl=""; is_end_with_repl=""; inputtype=none; is_silent=1 ;;
            *)
                            [ "$1" != -- ] || shift
                            if [ -z "$question" ]; then
                                question="$*"
                            else
                                question="${question} $*"
                            fi
                            break
                            ;;
        esac
    done

    [ -n "$inputtype" ] || {
        if [ -t 0 ]; then   inputtype=none
        else                inputtype=pipe
        fi
    }

    case "$inputtype" in
        pipe)
            ___x_cmd_chat___exec_pipe_ "$inputdesc" "$numbered" || return $?
            reflist="${reflist}${x_}${NL}"
            x_=""
            is_no_empty_question=""
            ;;
    esac

    if [ "$is_start_with_repl" = 1 ]; then
        ___x_cmd_chat___exec_repl --start "$question"
        return
    elif [ -z "$question" ]; then
        if [ "$is_no_empty_question" = 1 ]; then
            chat:error "Please provide the text you want request"
            return 1
        elif [ -z "${minion}${system}" ]; then
            ___x_cmd_chat___exec_repl --app
            return
        fi
    fi

    # x_=; ___x_cmd_chat_request___preparequestion_ "$question" "$inputtype" "$numbered" "$inputdesc" || return $?
    # question="$x_"

    if [ "$is_end_with_repl" = 1 ]; then
        [ -n "$session" ] || {
            x_=""; ___x_cmd_chat___exec_repl___id_ || return $?
            session="$x_"
        }
        ___x_cmd_chat___exec_raw "$question" "$history_num" "$reflist" "$filelist_attach"
        [ -z "$question" ] || ___x_cmd_chat___exec_repl_history add "$question"

        ___x_cmd_chat___exec_repl --previous
        return
    else
        ___x_cmd_chat___exec_raw "$question" "$history_num" "$reflist" "$filelist_attach"
    fi
}

# question reflist filelist_attach
___x_cmd_chat___exec_raw(){
    local question="$1"
    local history_num="$2"
    local reflist="$3"
    local filelist_attach="$4"

    envinfo="$(___x_cmd_chat___exec_envinfo)" \
        ___x_cmd_chat___exec_inner
}

___x_cmd_chat___exec_inner(){
    local question="$question"
    local x_=; ___x_cmd str trimm_ "$reflist"
    question="${x_}${question}"

    # TODO: scan the question, extract url.
    # Prompt to ask whether to extract the content from the url using jina

    # @gemini "Please summary the data [ddgo:]"

    local cfg_history_num=; local cfg_session=;     local cfg_minion=;  local cfg_userlang=; local cfg_stream=""; local cfg_reasoning=""
    ___x_cmd_chat_cfg --var cfg_history_num=history cfg_session=session cfg_minion=minion cfg_userlang=userlang cfg_stream=stream cfg_reasoning=reasoning 2>/dev/null

    minion="${minion:-"$cfg_minion"}"
    minion="${minion:-"default"}"
    x_=; ___x_cmd_chat_minion_cache_json_ "$minion" || return $?
    local minion_json_cache="$x_"

    local chatid;   chatid="$( ___x_cmd pidid vlseqid ___X_CMD_CHAT_REC )"
    chat:debug --chatid "$chatid" --model "$model" --cfg_stream "$cfg_stream" --cfg_reasoning "$cfg_reasoning" --history_num "$history_num" --confirm_before_send "$confirm_before_send" --question "$question" "chat exec"

    local XCMD_CHAT_IS_INTERACTIVE="$is_interactive"
    local XCMD_CHAT_SESSION=""
    local XCMD_CHAT_HISTSESSION=""
    local XCMD_CHAT_SESSION_DIR=""
    local XCMD_CHAT_HISTSESSION_DIR=""
    local XCMD_CHAT_ENACTALL_LOGFILE=""
    local XCMD_CHAT_ENACTALL_DRAWFILE=""

    session="$(___x_cmd_chat_minion getitem "$minion_json_cache" session)"
    [ -n "$session" ] || N=chat M="The session name is empty, please check the minion file" log:ret:64
    XCMD_CHAT_SESSION_DIR="$___X_CMD_CHAT_SESSION_DIR/$session"
    XCMD_CHAT_SESSION="$session"
    if [ -z "$hist_session" ]; then
        XCMD_CHAT_HISTSESSION="$session"
        XCMD_CHAT_HISTSESSION_DIR="$XCMD_CHAT_SESSION_DIR"
    else
        XCMD_CHAT_HISTSESSION="$hist_session"
        XCMD_CHAT_HISTSESSION_DIR="$___X_CMD_CHAT_SESSION_DIR/$hist_session"
    fi

    XCMD_CHAT_ENACTALL_LOGFILE="$XCMD_CHAT_SESSION_DIR/$chatid/log"
    XCMD_CHAT_ENACTALL_DRAWFILE="$XCMD_CHAT_SESSION_DIR/$chatid/draw"

    if [ "$is_enactnone" != 1 ]; then
        ___x_cmd_chat___exec__histsum || return $?
        ___x_cmd ensurefp "$XCMD_CHAT_ENACTALL_LOGFILE"
        printf "%s" "" > "$XCMD_CHAT_ENACTALL_LOGFILE"
        printf "%s" "" > "$XCMD_CHAT_ENACTALL_DRAWFILE"

        (
            ___x_cmd_chat___exec_inner_provider_ & \
                ___x_cmd coco enactall "$XCMD_CHAT_SESSION_DIR/$chatid"
        )
    else
        ___x_cmd_chat___exec_inner_provider_ || return $?
        printf "%s\n" "$XCMD_CHAT_SESSION_DIR/$chatid"
    fi
}

___x_cmd_chat___exec_inner_provider_(){
    [ "$is_enactnone" = 1 ] || printf "[MODEL-SENT-AT] %s\n" "${EPOCHREALTIME:-"$(date +%s)"}" >> "$XCMD_CHAT_ENACTALL_DRAWFILE"

    [ -z "$is_silent" ] || ___x_cmd log "$provider"/warn 2>/dev/null
    case "$provider" in
        gh) ___x_cmd "$provider" model chat exec ;;
        *)  ___x_cmd "$provider" chat exec ;;
    esac
    local _exitcode="$?"
    if [ "$is_enactnone" != 1 ] && [ "$_exitcode" != 0 ]; then
        printf "[EXITCODE] %s\n" "$_exitcode" >> "$XCMD_CHAT_ENACTALL_DRAWFILE"
        printf "[BREAK] %s\n" "$_exitcode" >> "$XCMD_CHAT_ENACTALL_LOGFILE"
    fi
    return "$_exitcode"
}

___x_cmd_chat___exec__cancel_request(){
    ___X_CMD_RETRY_ABORT=1
    if [ "$is_enactnone" != 1 ]; then
        printf "\n%s\n" "[EXITCODE] 130"    >> "$XCMD_CHAT_ENACTALL_DRAWFILE"
        printf "\n%s\n" "[BREAK] 130"    >> "$XCMD_CHAT_ENACTALL_LOGFILE"
    fi
    printf "%s\n" "Cancel the request"  >> "$XCMD_CHAT_SESSION_DIR/$chatid/chat.error.yml"
}

___x_cmd_chat___exec__confirm_before_request(){
    [ -z "$confirm_before_send" ] || {
        < "$request_body_file" ___x_cmd j2y | ___x_cmd bat -l yml --wrap never >"$___X_CMD_DEVTTY_FP"
        ___x_cmd ui yesno "Do your want to send this message?" || {
            ___x_cmd_chat___exec__cancel_request
            return 1
        }
        confirm_before_send=
    }
}

___x_cmd_chat___exec__histsum(){
    local histsession="$XCMD_CHAT_HISTSESSION"
    local history_num="$(___x_cmd_chat_minion getitem "$minion_json_cache" history_num)"
    [ "$history_num" -gt 0 ] || return 0
    chat:debug --histsession "$histsession" --XCMD_CHAT_HISTSESSION_DIR "$XCMD_CHAT_HISTSESSION_DIR" --history_num "$history_num" "check histsum"
    [ -d "$XCMD_CHAT_HISTSESSION_DIR" ] || return 0

    local l=""; local n=0; local filename=""
    { ___x_cmd_cmds find "$XCMD_CHAT_HISTSESSION_DIR" -type f -name "histsum.md" -o -path "*/chat.response/content" | ___x_cmd_cmds sort -r; } 2>/dev/null | {
        while read -r l; do
            l="${l#"$XCMD_CHAT_HISTSESSION_DIR/"}"
            filename="${l#*/}"
            n="$((n+1))"
            [ "$n" -le "$history_num" ] || break
            [ "$filename" != "histsum.md" ] || break
        done
        [ "$n" -gt "$history_num" ] || return 0

        ___x_cmd coco histsum "$histsession"
    }
}
