#!/bin/sh
set -eu

project_root=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
config_file="$project_root/.dingtalk/config.env"

usage() {
  echo "用法：./scripts/dingtalk-progress <start|milestone|blocked|complete|failed> <中文 Markdown 摘要>" >&2
}

if [ "$#" -lt 2 ]; then
  usage
  exit 2
fi

event_name=$1
shift
summary=$*

case "$event_name" in
  start|milestone|blocked|complete|failed) ;;
  *)
    usage
    exit 2
    ;;
esac

if [ ! -f "$config_file" ]; then
  echo "DingTalk progress reporting is not configured; skipping." >&2
  exit 0
fi

file_mode=$(stat -f '%Lp' "$config_file" 2>/dev/null || stat -c '%a' "$config_file" 2>/dev/null || true)
case "$file_mode" in
  400|600) ;;
  *)
    echo "Refusing to read $config_file because its mode is ${file_mode:-unknown}; run chmod 600 on it." >&2
    exit 2
    ;;
esac

while IFS= read -r line || [ -n "$line" ]; do
  case "$line" in
    ''|'#'*) continue ;;
  esac
  key=${line%%=*}
  value=${line#*=}
  case "$key" in
    DINGTALK_PROGRESS_ENABLED|DINGTALK_PROGRESS_DRY_RUN|DINGTALK_PROGRESS_MODE|DINGTALK_PROGRESS_CLIENT_ID|DINGTALK_PROGRESS_TARGET|DINGTALK_PROGRESS_ROBOT_CODE|DINGTALK_PROGRESS_KEYCHAIN_SERVICE|DINGTALK_PROGRESS_PROJECT|DINGTALK_PROGRESS_TITLE_PREFIX)
      export "$key=$value"
      ;;
    *)
      echo "Unknown key in $config_file: $key" >&2
      exit 2
      ;;
  esac
done < "$config_file"

if [ "${DINGTALK_PROGRESS_ENABLED:-0}" != "1" ]; then
  echo "DingTalk progress reporting is disabled; skipping." >&2
  exit 0
fi

if [ "${DINGTALK_PROGRESS_MODE:-app-bot}" != "app-bot" ]; then
  echo "DINGTALK_PROGRESS_MODE must be app-bot." >&2
  exit 2
fi

if [ -z "${DINGTALK_PROGRESS_CLIENT_ID:-}" ] ||
   [ -z "${DINGTALK_PROGRESS_TARGET:-}" ] ||
   [ -z "${DINGTALK_PROGRESS_ROBOT_CODE:-}" ]; then
  echo "App-bot mode requires DINGTALK_PROGRESS_CLIENT_ID, DINGTALK_PROGRESS_TARGET, and DINGTALK_PROGRESS_ROBOT_CODE." >&2
  exit 2
fi

if ! command -v jq >/dev/null 2>&1; then
  echo "jq is required to construct and validate the DingTalk OpenAPI request." >&2
  exit 127
fi

if ! command -v dws >/dev/null 2>&1; then
  echo "Global dws command was not found in PATH." >&2
  exit 127
fi
dws=$(command -v dws)

if [ -n "${DING_SEC:-}" ]; then
  client_secret=$DING_SEC
else
  if [ ! -x /usr/bin/security ]; then
    echo "DING_SEC is unset and macOS Keychain command /usr/bin/security is unavailable." >&2
    exit 127
  fi

  keychain_service=${DINGTALK_PROGRESS_KEYCHAIN_SERVICE:-com.eapil.dingtalk.$(basename -- "$project_root")}
  if ! client_secret=$(/usr/bin/security find-generic-password \
    -a "$DINGTALK_PROGRESS_CLIENT_ID" \
    -s "$keychain_service" \
    -w 2>/dev/null); then
    echo "DingTalk Client Secret was not found in DING_SEC or this project's macOS Keychain item." >&2
    echo "See .dingtalk/README.md for credential setup." >&2
    exit 2
  fi
fi

if [ -z "$client_secret" ]; then
  echo "The DingTalk Client Secret is empty." >&2
  exit 2
fi

case "$event_name" in
  start) event_label="开始推进" ;;
  milestone) event_label="阶段里程碑" ;;
  blocked) event_label="遇到阻塞" ;;
  complete) event_label="本轮完成" ;;
  failed) event_label="执行失败" ;;
esac

project_name=${DINGTALK_PROGRESS_PROJECT:-$(basename -- "$project_root")}
title_prefix=${DINGTALK_PROGRESS_TITLE_PREFIX:-[项目进度]}
title="$title_prefix $event_label"
timestamp=$(date '+%Y-%m-%d %H:%M:%S %Z')
body=$(printf '## %s\n\n**项目：** %s  \n**状态：** %s  \n**更新时间：** %s\n\n---\n\n%s' \
  "$title" "$project_name" "$event_label" "$timestamp" "$summary")

msg_param=$(jq -cn --arg title "$title" --arg text "$body" '{title:$title,text:$text}')
request_body=$(jq -cn \
  --arg msgParam "$msg_param" \
  --arg openConversationId "$DINGTALK_PROGRESS_TARGET" \
  --arg robotCode "$DINGTALK_PROGRESS_ROBOT_CODE" \
  '{msgParam:$msgParam,msgKey:"sampleMarkdown",openConversationId:$openConversationId,robotCode:$robotCode}')

if [ "${DINGTALK_PROGRESS_DRY_RUN:-0}" = "1" ]; then
  if DWS_CLIENT_ID="$DINGTALK_PROGRESS_CLIENT_ID" \
     DWS_CLIENT_SECRET="$client_secret" \
     "$dws" api POST /v1.0/robot/groupMessages/send \
       --data "$request_body" --dry-run --yes --format json; then
    send_status=0
  else
    send_status=$?
  fi
  unset client_secret DWS_CLIENT_SECRET
  exit "$send_status"
fi

max_send_attempts=3
retry_delay_seconds=10
attempt=1
final_status=1

while [ "$attempt" -le "$max_send_attempts" ]; do
  response=
  if response=$(DWS_CLIENT_ID="$DINGTALK_PROGRESS_CLIENT_ID" \
    DWS_CLIENT_SECRET="$client_secret" \
    "$dws" api POST /v1.0/robot/groupMessages/send \
      --data "$request_body" --yes --format json); then
    send_status=0
  else
    send_status=$?
  fi

  if [ -n "$response" ]; then
    printf '%s\n' "$response"
  fi

  if [ "$send_status" -eq 0 ] &&
     printf '%s\n' "$response" |
       jq -e '.processQueryKey | type == "string" and length > 0' >/dev/null 2>&1; then
    unset client_secret DWS_CLIENT_SECRET
    exit 0
  fi

  if [ "$send_status" -eq 0 ]; then
    echo "DingTalk attempt $attempt returned no valid processQueryKey; service acceptance is unverified." >&2
    final_status=1
  else
    echo "DingTalk attempt $attempt failed with status $send_status." >&2
    final_status=$send_status
  fi

  if [ "$attempt" -lt "$max_send_attempts" ]; then
    echo "Retrying DingTalk send in $retry_delay_seconds seconds." >&2
    sleep "$retry_delay_seconds"
  fi
  attempt=$((attempt + 1))
done

unset client_secret DWS_CLIENT_SECRET
echo "DingTalk progress reporting failed after $max_send_attempts attempts; Etunel work should continue." >&2
exit "$final_status"
