# 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/shortcut 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 minion=""
    local session=""
    local hist_session=""
    local model=""
    local system=""
    local type="chat"
    local confirm_before_send=""
    # local question_op=""
    local count_token=""
    local attach_filelist=""
    local provider="gemini"
    local numbered=""
    local temperature=""
    local maxtoken=""
    local history_num=""
    local seed=""
    local attach_text=""
    local attach_system=""

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

    local NL="${___X_CMD_UNSEENCHAR_NEWLINE}"

    local cache_time=1h
    local modellist=""
    local require_question=""
    local attach_tool_schema=""

    local is_silent=""
    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=""
    local is_use_context_file=""
    local is_tool_force=""

    local run_mode=""

    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 $?
                            attach_text="${attach_text}${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 $?
                            attach_text="${attach_text}${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 $?
                            attach_text="${attach_text}${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 $?
                            attach_text="${attach_text}${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 $?
                            attach_text="${attach_text}${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 $?
                            attach_text="${attach_text}${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
                                attach_filelist="${attach_filelist}${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
                            ;;
            # --context)
            --system)       system="$2";            [ $# -ge 2 ] || N=chat M="Please provide the system value"  log:ret:64; shift 2 ;;
            --attach-system)
                            [ $# -ge 2 ] || N=chat M="Please provide the system value"  log:ret:64
                            attach_system="${attach_system}${2}${NL}"
                            shift 2 ;;
            --tool|--allowed-tools)
                            [ $# -ge 2 ] || N=chat M="Please provide the tools name" log:ret:64
                            attach_tool_schema="$( ___x_cmd coco toolspec invoke --json "$2" )" || return $?
                            attach_system="${attach_system}$( ___x_cmd coco toolspec prompt )${NL}" || return $?
                            shift 2 ;;
            --tool-force)   is_tool_force=1;        shift 1 ;;
            --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 ;;

            # deprecated ...
            --question)     question="$2";          [ $# -ge 2 ] || N=chat M="Please provide the question value" log:ret:64;  shift 2 ;;
            --attach-text)  attach_text="${attach_text}${2}${NL}";
                            [ $# -ge 2 ] || N=chat M="Please provide the append text 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 ;;
            --silent)       is_silent=1;            shift 1 ;;
            --help|-h)
                            case "$provider" in
                                hub)    ___x_cmd help -m hub ai convo request ;;
                                gh)     ___x_cmd help -m gh model chat request ;;
                                *)      ___x_cmd help -m "$provider" chat request   ;;
                            esac
                            return
                            ;;
            --style|--run-mode)
                            run_mode="$2";           [ $# -ge 2 ] || N=chat M="Please provide the run mode value" log:ret:64; shift 2
                            ;;
            --no-empty-question|--require-question)
                            require_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=0;  shift 1 ;;
            --end-without-repl)
                            is_end_with_repl=0;    shift 1 ;;
            --without-repl)
                            is_start_with_repl=0; is_end_with_repl=0; shift 1 ;;
            --interactive)      is_interactive=1;   shift 1 ;;
            --no-interactive)   is_interactive=0;   shift 1 ;;
            --enactnone)        is_enactnone=1;     shift 1
                                is_stream=0; is_start_with_repl=0; is_end_with_repl=0; inputtype=none; is_silent=1 ;;
            --use-context-file) is_use_context_file=1; shift 1 ;;
            --no-context-file)  is_use_context_file=0; shift 1 ;;

            *)
                            [ "$1" != -- ] || shift
                            if [ -z "$question" ]; then
                                question="$*"
                            else
                                question="${question} $*"
                            fi
                            break
                            ;;
        esac
    done

    case "$run_mode" in
        "")     ;;
        once)
                history_num="${history_num:-0}"
                is_use_context_file="${is_use_context_file:-0}"
                is_start_with_repl="${is_start_with_repl:-0}"
                is_end_with_repl="${is_end_with_repl:-0}"
                ;;
        chat|conversation)
                history_num="${history_num:-10}"
                is_use_context_file="${is_use_context_file:-1}"
                is_start_with_repl="${is_start_with_repl:-0}"
                if ___x_cmd_is_stdout2tty && ___x_cmd_runmode_allow_chatty; then
                    is_end_with_repl="${is_end_with_repl:-1}"
                fi
                ;;
        *)      N=chat M="Unsupported run mode ==> $run_mode" log:ret:64 ;;
    esac

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

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

    if [ "$is_start_with_repl" = 1 ]; then
        ___x_cmd_chat___exec_repl --start "$question"
        return
    elif [ -z "${question}${attach_text}${attach_filelist}" ]; then
        if [ "$require_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

    case "$run_mode" in
        once)
                session="${session:-"X"}"
                ;;
        chat|conversation)
                [ -n "$session" ] || {
                    x_=""; ___x_cmd_chat___exec_repl___id_ || return $?
                    session="$x_"
                }
                ;;
    esac

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

    if [ "$is_end_with_repl" = 1 ]; then
        ___x_cmd_chat___exec_raw "$question" "$history_num" "$attach_text" "$attach_filelist" || return $?
        [ -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" "$attach_text" "$attach_filelist"
    fi
}

# question attach_text attach_filelist
___x_cmd_chat___exec_raw(){
    local question="$1"
    local history_num="$2"
    local attach_text="$3"
    local attach_filelist="$4"
    local ___X_CMD_LOG_C_TF="$___X_CMD_LOG_C_TF"
    [ -n "$___X_CMD_LOG_C_TF" ] || [ -t 2 ] || ___X_CMD_LOG_C_TF=0

    ___X_CMD_LOG_C_TF="$___X_CMD_LOG_C_TF" \
    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_ "$attach_text"
    attach_text="${x_}"

    # 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_"
    x_=; ___x_cmd_chat___exec__get_context_filelist_ || return $?
    local context_filelist="$x_"

    local XCMD_CHAT_IS_INTERACTIVE="$is_interactive"
    local XCMD_CHAT_IS_TOOL_FORCE="$is_tool_force"
    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

    local chatid;   chatid="$( ___x_cmd pidid vlseqid ___X_CMD_CHAT_REC )"
    chat:debug --run_mode "$run_mode"  --chatid "$chatid" --session "$session" --provider "$provider" --model "$model" \
        --minion_json_cache "$minion_json_cache" --is_use_context_file "$is_use_context_file" \
        --context_filelist "$context_filelist" --cfg_stream "$cfg_stream" --cfg_reasoning "$cfg_reasoning" \
        --history_num "$history_num" --confirm_before_send "$confirm_before_send" "chat exec"

    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"


    [ "$is_enactnone" = 1 ] || ___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"
    ) || return $?

    [ "$is_enactnone" != 1 ] || printf "%s\n" "$XCMD_CHAT_SESSION_DIR/$chatid"
}

___x_cmd_chat___exec_inner_provider_(){
    ___x_cmd price check || return $?
    printf "[MODEL-SENT-AT] %s\n" "${EPOCHREALTIME:-"$(date +%s)"}" >> "$XCMD_CHAT_ENACTALL_DRAWFILE"

    [ "$is_silent" != 1 ] || ___x_cmd log "$provider"/warn 2>/dev/null
    case "$provider" in
        gh)     ___x_cmd gh model chat exec ;;
        hub)    ___x_cmd hub ai convo exec ;;
        *)      ___x_cmd "$provider" chat exec ;;
    esac
    local _exitcode="$?"
    if [ "$_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
    printf "\n%s\n" "[EXITCODE] 130"    >> "$XCMD_CHAT_ENACTALL_DRAWFILE"
    printf "\n%s\n" "[BREAK] 130"       >> "$XCMD_CHAT_ENACTALL_LOGFILE"
    printf "%s\n" "Cancel the request"  >> "$XCMD_CHAT_SESSION_DIR/$chatid/chat.error.yml"
}

___x_cmd_chat___exec__confirm_before_request(){
    [ "$confirm_before_send" != 1 ] || {
        < "$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=0
    }
}

___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 find --cmd "$XCMD_CHAT_HISTSESSION_DIR" -type f -name "histsum.md" -o -path "*/chat.response/done" | ___x_cmd_cmds sort -r; } 2>/dev/null | {
        while read -r l; do
            case "$l" in
                */histsum.md) n="$((n+1))"; break ;;
                */chat.response/done)
                    reqfile="${l%"/chat.response/done"}/chat.request/content"
                    [ -f "$reqfile" ] || continue
                    n="$((n+1))"
                    [ "$n" -le "$history_num" ] || break
                    ;;
            esac
        done
        [ "$n" -gt "$history_num" ] || return 0

        ___x_cmd coco histsum "$histsession"
    }
}

___x_cmd_chat___exec__get_context_filelist_(){
    x_=""
    [ "$is_use_context_file" = 1 ] || return 0
    local filename=""
    ___x_cmd_chat_cur filename:=context_filename 2>/dev/null
    filename="${filename:-"AGENTS.md"}"
    set -- "$PWD/$filename"

    x_=""
    if ___x_cmd wsroot_; then
        set -- "$x_/.x-cmd/$filename" "$@"
    fi

    x_=""
    local i=; for i in "$@" ; do
        [ -f "$i" ] || continue
        x_="${x_}${i}
"
    done
}
