#!/bin/bash

# ==========================================
# Jiaotu Workflow v13.0 (Scene/Output/Hyacine)
# ==========================================

ACCOUNTS_FILE="./accounts.txt"

# --- 日志工具 ---
log_info() { echo -e "\033[0;32m[INFO] $1\033[0m" >&2; }
log_warn() { echo -e "\033[0;33m[WARN] $1\033[0m" >&2; }
log_err() { echo -e "\033[0;31m[ERROR] $1\033[0m" >&2; }
log_step() { echo -e "\033[0;36m=== $1 ===\033[0m" >&2; }

# --- [更新] 详细帮助菜单 ---
show_usage() {
    cat <<EOF
================================================================
               JIAOTU AI WORKFLOW v13.0
================================================================
用法:
  $(basename "$0") [参数选项...]

前置条件:
  脚本同目录下必须存在 'accounts.txt' (格式: TOKEN SESSION)

----------------------------------------------------------------
[基础参数]
  --img <URL>        输入图片链接 (支持多次调用)。
  --output <DIR>     指定图片保存目录 (默认为当前目录)。
  -h, --help         显示本帮助文档。

----------------------------------------------------------------
[Cosplay 场景设置] (互斥，仅对 Cosplay 模式有效)
  (默认)             默认场景为 "by a seaside beach"。
  --lake             切换场景为 "by a lake"。
  --comimarket       切换场景为 "at a comimarket"。
  --screenshot       截图模式 (保留原背景和UI)，忽略上述场景设置。

[Cosplay 动作设置]
  --bikini           开启比基尼模式 (引用比基尼参考图)。
  --kiss             开启接吻动作 (French kiss holding hands)。
  --hug              开启拥抱动作 (Hug looking at camera)。

----------------------------------------------------------------
[Gacha 替换模式] (Cyrene / Hyacine)
  --name <NAME>      指定替换后的角色名称 (必需)。
  --element <URL>    指定属性图标链接 (用于替换原属性)。

  --cyrene           [模式A] 替换 Cyrene (冰属性模板)。
  --cyrene-pose      在 Cyrene 模式下强制模仿姿态。

  --hyacine          [模式B] 替换 Hyacine (风属性模板)。
                     * 提示词自动调整为 replace hyacine / wind icon。
                     * 使用独立的 Hyacine 常量图 ID。
  --hyacine-pose     在 Hyacine 模式下强制模仿姿态。

----------------------------------------------------------------
[典型示例]

  1. 湖边比基尼:
     $0 --img "http://url..." --lake --bikini

  2. 漫展拥抱:
     $0 --img "http://url1..." --img "http://url2..." --comimarket --hug

  3. 指定保存路径:
     $0 --img "http://url..." --output "/home/user/images"

  4. Hyacine 替换 (风属性模板):
     $0 --img "http://char.jpg" --hyacine --name "Feixiao" --element "http://wind.png"

================================================================
EOF
}

# --- 仅检查余额 ---
check_balance_only() {
    local C_TOKEN="$1"
    local C_SESSION="$2"
    C_TOKEN=$(echo "$C_TOKEN" | tr -d '\r\n ')
    C_SESSION=$(echo "$C_SESSION" | tr -d '\r\n ')

    curl -s 'https://api.jiaotuai.cn/api/v1/sign/getSing' \
      -H "Authorization: Bearer ${C_TOKEN}" \
      -H 'Content-Type: application/json' \
      -H 'User-Agent: Mozilla/5.0' -o /dev/null
    
    local RESP=$(curl -s 'https://api.jiaotuai.cn/api/v1/product/queryPackageCount' \
      -H "Authorization: Bearer ${C_TOKEN}" \
      -H 'Content-Type: application/json' \
      -H 'User-Agent: Mozilla/5.0' \
      -H "Referer: https://www.jiaotuai.cn/studio?sessionId=${C_SESSION}")
    
    local AVAIL=$(echo "$RESP" | grep -oE '"availableCount":[0-9]+' | grep -oE '[0-9]+' | head -n 1)
    echo "${AVAIL:-0}"
}

# --- 核心工作流 ---
jiaotu_workflow() {
    local TOKEN="$1"; shift
    local SESSION="$1"; shift
    TOKEN=$(echo "$TOKEN" | tr -d '\r\n ')
    SESSION=$(echo "$SESSION" | tr -d '\r\n ')

    # 变量初始化
    local IMAGES_URLS=()
    local ELEMENT_URL=""
    local OUTPUT_DIR="."  # 默认当前目录
    
    # 模式开关
    local MODE_BIKINI=false
    local MODE_KISS=false
    local MODE_HUG=false
    local MODE_SCREENSHOT=false
    
    # 场景开关 (默认 seaside)
    local SCENE_TYPE="beach" 
    
    # Gacha 模式开关
    local MODE_CYRENE=false
    local MODE_CYRENE_POSE=false
    local MODE_HYACINE=false
    local MODE_HYACINE_POSE=false
    
    local CHAR_NAME=""
    
    # 常量 ID
    local CONST_ID_BIKINI="2012598262529208321"
    local CONST_ID_CYRENE="2012623834793848833"
    local CONST_ID_HYACINE="2012763532602322946"

    # 参数解析
    while [[ $# -gt 0 ]]; do
        case "$1" in
            --img) if [[ -n "$2" && "$2" != --* ]]; then IMAGES_URLS+=("$2"); shift; fi ;;
            --element) if [[ -n "$2" ]]; then ELEMENT_URL="$2"; shift; fi ;;
            --name) if [[ -n "$2" ]]; then CHAR_NAME="$2"; shift; fi ;;
            --output) if [[ -n "$2" ]]; then OUTPUT_DIR="$2"; shift; fi ;;
            
            # 动作
            --bikini) MODE_BIKINI=true ;;
            --kiss) MODE_KISS=true ;;
            --hug) MODE_HUG=true ;;
            
            # 场景
            --screenshot) MODE_SCREENSHOT=true ;;
            --lake) SCENE_TYPE="lake" ;;
            --comimarket) SCENE_TYPE="comimarket" ;;
            
            # Cyrene 系列
            --cyrene) MODE_CYRENE=true ;;
            --cyrene-pose) MODE_CYRENE=true; MODE_CYRENE_POSE=true ;;
            
            # Hyacine 系列
            --hyacine) MODE_HYACINE=true ;;
            --hyacine-pose) MODE_HYACINE=true; MODE_HYACINE_POSE=true ;;
            
            *) if [[ "$1" == http* ]]; then IMAGES_URLS+=("$1"); fi ;;
        esac
        shift
    done

    # 校验
    if [[ ("$MODE_CYRENE" == true || "$MODE_HYACINE" == true) && -z "$CHAR_NAME" ]]; then 
        log_err "Cyrene/Hyacine 模式需要 --name"; return 1; 
    fi

    # 准备输出目录
    if [[ ! -d "$OUTPUT_DIR" ]]; then
        mkdir -p "$OUTPUT_DIR" || { log_err "无法创建目录: $OUTPUT_DIR"; return 1; }
    fi

    # Step 1
    log_step "Step 1: Account Confirmation"
    local POINTS=$(check_balance_only "$TOKEN" "$SESSION")
    log_info "Current Balance: $POINTS"
    
    # Step 2
    log_step "Step 2: Uploading Inputs"
    local UPLOADED_IDS=()
    
    upload_stream() {
        local TARGET_URL="$1"
        local VNAME="stream_$(date +%s)_$RANDOM.jpg"
        
        # Token
        local BODY_T=$(printf '{"sessionId":"%s","fileName":"%s"}' "$SESSION" "$VNAME")
        local RESP_T=$(curl -s -X POST "https://api.jiaotuai.cn/api/v1/upload/token" \
            -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d "$BODY_T")
        
        local UP_URL=$(echo "$RESP_T" | sed -nE 's/.*"uploadUrl":"([^"]+)".*/\1/p')
        local CB_TOKEN=$(echo "$RESP_T" | sed -nE 's/.*"callbackToken":"([^"]+)".*/\1/p')
        
        if [[ -z "$UP_URL" ]]; then log_err "Upload Token Error: $TARGET_URL"; return 1; fi
        
        # Upload
        log_info "正在流式传输: ${TARGET_URL:0:40}..." >&2
        local CODE=$(curl -L "$TARGET_URL" -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' 2>/dev/null \
            | curl -s -w "%{http_code}" -X PUT "$UP_URL" -H "Content-Type: image/jpeg" --data-binary @- -o /dev/null)
        
        if [[ "$CODE" != "200" ]]; then log_err "HTTP $CODE Error"; return 1; fi
        
        # Callback
        local BODY_C=$(printf '{"callbackToken":"%s","fileName":"%s"}' "$CB_TOKEN" "$VNAME")
        local RESP_C=$(curl -s -X POST "https://api.jiaotuai.cn/api/v1/upload/callback" \
            -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d "$BODY_C")
        
        local RET_ID=$(echo "$RESP_C" | grep -oE '"(data|id|ossId)":"?[0-9]+' | grep -oE '[0-9]+' | head -n 1)
        if [[ -z "$RET_ID" ]]; then log_err "Callback Error"; return 1; fi
        echo "$RET_ID"
    }

    # 上传用户图
    for img in "${IMAGES_URLS[@]}"; do
        local uid=$(upload_stream "$img")
        if [[ -n "$uid" ]]; then UPLOADED_IDS+=("$uid"); log_info "Uploaded: $uid"; else return 1; fi
    done
    
    # 上传元素图
    local ELE_ID=""
    if [[ -n "$ELEMENT_URL" ]]; then
        ELE_ID=$(upload_stream "$ELEMENT_URL")
        if [[ -z "$ELE_ID" ]]; then return 1; fi
        log_info "Element ID: $ELE_ID"
    fi

    # Step 3
    log_step "Step 3: Constructing Prompt"
    local FINAL_PROMPT=""
    local FINAL_IDS_JSON=""

    # === 场景逻辑 (Scene) ===
    # 仅在非 Screenshot 模式下生效
    local SCENE_TEXT="by a seaside beach"
    if [[ "$SCENE_TYPE" == "lake" ]]; then SCENE_TEXT="by a lake"
    elif [[ "$SCENE_TYPE" == "comimarket" ]]; then SCENE_TEXT="at a comimarket"
    fi

    # === 分支 A: Cyrene / Hyacine 模式 ===
    if [[ "$MODE_CYRENE" == true || "$MODE_HYACINE" == true ]]; then
        if [[ ${#UPLOADED_IDS[@]} -eq 0 ]]; then log_err "Need input image"; return 1; fi
        
        local VAR_ID="${UPLOADED_IDS[0]}"
        
        # 默认 Cyrene 配置
        local REF_CONST_ID="$CONST_ID_CYRENE"
        local REF_NAME="cyrene"
        local REF_ICON="ice"
        local IS_POSE_MODE="$MODE_CYRENE_POSE"
        
        # Hyacine 覆写
        if [[ "$MODE_HYACINE" == true ]]; then
            REF_CONST_ID="$CONST_ID_HYACINE"
            REF_NAME="hyacine"
            REF_ICON="wind"
            IS_POSE_MODE="$MODE_HYACINE_POSE"
        fi

        local IDS_STR="\"${VAR_ID}\",\"${REF_CONST_ID}\""
        
        # 提示词构建 (使用单引号包裹变量名)
        FINAL_PROMPT="pls replace ${REF_NAME} in the second pic with ${CHAR_NAME} in the first pic,\\nand make sure the character name in the second pic to be '${CHAR_NAME}',"

        if [[ "$IS_POSE_MODE" == true ]]; then 
            FINAL_PROMPT="${FINAL_PROMPT}\\nand make sure ${CHAR_NAME} replicate the same pose, body posture, facial expression, and camera framing as ${REF_NAME}. Keep the same angle, perspective, and composition, without any deviation,"
        fi
        
        if [[ -n "$ELE_ID" ]]; then 
            FINAL_PROMPT="${FINAL_PROMPT}\\nand replace ${REF_ICON} icon in the pic with lightning icon in pic3,"
            IDS_STR="${IDS_STR},\"${ELE_ID}\""
        fi
        
        FINAL_PROMPT="${FINAL_PROMPT}\\nand make the other ui element in the second pic intact"
        FINAL_IDS_JSON="[${IDS_STR}]"

    # === 分支 B: Cosplay 模式 ===
    else
        local CNT=${#UPLOADED_IDS[@]}
        if [[ $CNT -eq 0 ]]; then log_err "Need input image"; return 1; fi
        
        # 开头
        if [[ "$MODE_KISS" == true || "$MODE_HUG" == true ]]; then
            if [[ $CNT -ge 2 ]]; then FINAL_PROMPT="pic 1 is character A and pic 2 is character B,\\npls Generate a highly detailed realistic cosplay photo of character A and character B,\\n"; else FINAL_PROMPT="pls Generate a highly detailed realistic cosplay photo of characters in pic1,\\n"; fi
        else FINAL_PROMPT="pls Generate a highly detailed realistic cosplay photo of character(s) in pic1,\\n"; fi
        
        # 发带
        FINAL_PROMPT="${FINAL_PROMPT}and preserve [their] headband if [they] had any,\\n"
        
        # Bikini
        local B_IDX=2; 
        if [[ "$MODE_BIKINI" == true ]]; then 
            if [[ $CNT -ge 2 ]]; then B_IDX=3; fi; 
            FINAL_PROMPT="${FINAL_PROMPT}and then add [them] with strapless micro bikini with color matchin' [their] hair color and shape matchin' pic [${B_IDX}],\\n"; 
        fi
        
        # 眼镜
        FINAL_PROMPT="${FINAL_PROMPT}and then add thin, metal frames in a round style glasses with transparent lens and frame color matchin' [their respective eye color] for [them],\\n"
        
        # 背景 (应用场景变量 SCENE_TEXT)
        if [[ "$MODE_SCREENSHOT" == true ]]; then 
            FINAL_PROMPT="${FINAL_PROMPT}and use the original background of [pic1], and make the ui elements of the original screenshot intact.\\n"
        else 
            FINAL_PROMPT="${FINAL_PROMPT}${SCENE_TEXT}.\\n"
        fi
        
        # 画质/动作
        FINAL_PROMPT="${FINAL_PROMPT}Keep [their] hair style as same as the original illustrations. Exactly replicate the same pose, body posture, hand gestures, facial expression, and camera framing as in the original illustrations. Keep the same angle, perspective, and composition, without any deviation,\\n"
        
        # 互动
        if [[ "$MODE_KISS" == true ]]; then FINAL_PROMPT="${FINAL_PROMPT}And make them do french kiss while holding hands,\\n"; elif [[ "$MODE_HUG" == true ]]; then FINAL_PROMPT="${FINAL_PROMPT}And make them hug each other but look at the camera,\\n"; fi
        
        # 结尾
        FINAL_PROMPT="${FINAL_PROMPT}and make the aspect ratio of this pic to be 16:9."
        
        # 构建 IDs
        local IDS_STR=""; for id in "${UPLOADED_IDS[@]}"; do if [[ -z "$IDS_STR" ]]; then IDS_STR="\"$id\""; else IDS_STR="$IDS_STR,\"$id\""; fi; done
        if [[ "$MODE_BIKINI" == true ]]; then IDS_STR="$IDS_STR,\"${CONST_ID_BIKINI}\""; fi
        FINAL_IDS_JSON="[${IDS_STR}]"
    fi

    # Step 4
    log_step "Step 4: Generating"
	# echo $FINAL_PROMPT 
    local POST_DATA="{\"prompt\":\"${FINAL_PROMPT}\",\"sessionId\":\"${SESSION}\",\"imagesIds\":${FINAL_IDS_JSON},\"size\":\"16:9\",\"qualityLevel\":\"4K\",\"modelId\":11}"
    
    local GEN_RES=$(curl -s -N 'https://api.jiaotuai.cn/api/v1/ai/imageChat' \
        --compressed -X POST -H 'User-Agent: Mozilla/5.0' -H 'Content-Type: application/json' \
        -H "Authorization: Bearer ${TOKEN}" -H "Referer: https://www.jiaotuai.cn/studio?sessionId=${SESSION}" \
        --data "${POST_DATA}")
    
    local GEN_ID=$(echo "$GEN_RES" | grep '"type":"image"' | sed -nE 's/.*"ossId":"([0-9]+)".*/\1/p' | tail -n 1)
    
    if [[ -z "$GEN_ID" ]]; then 
        log_err "Generation Failed"
        echo "$GEN_RES" | tail -n 1 >&2 
        return 1
    fi
    log_info "Gen ID: $GEN_ID"

    # Step 5
    log_step "Step 5: Downloading"
    local URL_RES=$(curl -s "https://api.jiaotuai.cn/api/v1/imageSession/getImageUrl?ossId=${GEN_ID}&imageType=2" -H "Authorization: Bearer ${TOKEN}" -H "Referer: https://www.jiaotuai.cn/")
    local FINAL_URL=$(echo "$URL_RES" | sed -nE 's/.*"data":"([^"]+)".*/\1/p')
    if [[ -z "$FINAL_URL" ]]; then return 1; fi
    
    # [更新] 使用指定目录保存
    local SAVE_NAME="jiaotu_$(date +%Y%m%d_%H%M%S)_${GEN_ID}.jpg"
    local SAVE_PATH="${OUTPUT_DIR}/${SAVE_NAME}"
    
    if curl -s -o "$SAVE_PATH" "$FINAL_URL"; then
        # 获取绝对路径用于显示
        local ABS_PATH=$(realpath "$SAVE_PATH" 2>/dev/null || echo "$SAVE_PATH")
        log_info "Saved to: $ABS_PATH"
    else
        log_err "Save failed."
    fi
    echo "$FINAL_URL"
}

# --- Main ---
main() {
    if [[ "$1" == "-h" || "$1" == "--help" ]]; then show_usage; return 0; fi
    if [[ ! -f "$ACCOUNTS_FILE" ]]; then log_err "File not found: $ACCOUNTS_FILE"; return 1; fi

    log_step "Initializing: Checking Account Pool..."
    local SELECTED_TOKEN=""
    local SELECTED_SESSION=""
    local ACCOUNT_INDEX=0

    while read -r line <&3 || [[ -n "$line" ]]; do
        [[ -z "$line" || "$line" == \#* ]] && continue
        ((ACCOUNT_INDEX++))
        
        local CUR_TOKEN=$(echo "$line" | awk '{print $1}' | tr -d '\r')
        local CUR_SESSION=$(echo "$line" | awk '{print $2}' | tr -d '\r')
        
        if [[ -z "$CUR_TOKEN" || -z "$CUR_SESSION" ]]; then continue; fi

        local POINTS=$(check_balance_only "$CUR_TOKEN" "$CUR_SESSION")
        if [[ "$POINTS" -ge 10 ]]; then
            log_info "✅ Account #$ACCOUNT_INDEX Selected! (Points: $POINTS)"
            SELECTED_TOKEN="$CUR_TOKEN"; SELECTED_SESSION="$CUR_SESSION"
            break
        else
            log_warn "❌ Account #$ACCOUNT_INDEX Insufficient Points ($POINTS). Trying next..."
        fi
    done 3< "$ACCOUNTS_FILE"

    if [[ -z "$SELECTED_TOKEN" ]]; then log_err "No available accounts."; return 1; fi
    
    log_step "Starting Workflow with Account #$ACCOUNT_INDEX"
    jiaotu_workflow "$SELECTED_TOKEN" "$SELECTED_SESSION" "$@"
}

if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    main "$@"
fi