# shellcheck shell=bash

trim_whitespace() {
  local value="${1-}"
  value="${value#"${value%%[![:space:]]*}"}"
  value="${value%"${value##*[![:space:]]}"}"
  printf '%s' "$value"
}

is_interactive_session() {
  [[ -t 0 && -t 1 ]]
}

split_task_key() {
  local raw_key=""
  raw_key="$(trim_whitespace "${TASK_KEY_INPUT-}")"

  if [[ -z "$raw_key" ]]; then
    return 0
  fi

  if [[ "$raw_key" != *:*:* ]]; then
    printf 'invalid --task-key value: %s (expected <project-id>:<task-group>:<task-id>)\n' "$raw_key" >&2
    exit 1
  fi

  local key_proj="${raw_key%%:*}"
  local key_rest="${raw_key#*:}"
  local key_group="${key_rest%%:*}"
  local key_id="${key_rest#*:}"

  if [[ -z "$key_proj" || -z "$key_group" || -z "$key_id" || "$key_id" == *:* ]]; then
    printf 'invalid --task-key value: %s (expected <project-id>:<task-group>:<task-id>)\n' "$raw_key" >&2
    exit 1
  fi

  if [[ -n "$PROJECT_ID" && "$PROJECT_ID" != "$key_proj" ]]; then
    printf '%s\n' "--task-key project-id ($key_proj) conflicts with --project-id ($PROJECT_ID)" >&2
    exit 1
  fi
  if [[ -n "$TASK_GROUP" && "$TASK_GROUP" != "$key_group" ]]; then
    printf '%s\n' "--task-key task-group ($key_group) conflicts with --task-group ($TASK_GROUP)" >&2
    exit 1
  fi
  if [[ -n "$TASK_ID" && "$TASK_ID" != "$key_id" ]]; then
    printf '%s\n' "--task-key task-id ($key_id) conflicts with --task-id ($TASK_ID)" >&2
    exit 1
  fi

  PROJECT_ID="$key_proj"
  TASK_GROUP="$key_group"
  TASK_ID="$key_id"
}

# okstra_ctl.interactive_cli 호출 공용 래퍼. 조회 로직은 전부 그 모듈에 있다 —
# 예전에는 이 파일이 파이썬 heredoc 6개(153줄)로 같은 일을 했고, 셸 문자열 안이라
# import 도 테스트도 닿지 않았다(docs/coding-rules.md R1).
_okstra_interactive_cli() {
  PYTHONPATH="${OKSTRA_PYTHONPATH}${PYTHONPATH:+:$PYTHONPATH}" \
    python3 -m okstra_ctl.interactive_cli "$@"
}

resolve_task_root_for_shortcut() {
  local project_root="$1"
  local project_id="$2"
  local task_group="$3"
  local task_id="$4"

  local resolved=""
  resolved="$(_okstra_interactive_cli resolve-task-root \
    --project-root "$project_root" --project-id "$project_id" \
    --task-group "$task_group" --task-id "$task_id")"

  local status=""
  status="$(printf '%s' "$resolved" | head -n 1 | awk -F '\t' '{print $1}')"

  if [[ "$status" == "OK" ]]; then
    printf '%s' "$resolved" | head -n 1 | awk -F '\t' '{print $2}'
    return 0
  fi

  printf 'task root not found for %s:%s:%s\n' "$project_id" "$task_group" "$task_id" >&2
  printf '%s\n' "$resolved" | awk -F '\t' '
    $1 == "TRIED"    { printf "  tried: %s\n", $2 }
    $1 == "AVAILABLE"{ avail = avail "    " $2 "\n" }
    END {
      if (avail != "") {
        printf "  available task-keys for this project (case- and slug-sensitive on disk):\n%s", avail
      }
    }' >&2
  printf '  hint: task-key lookup is case-insensitive against task-catalog.json. Group / id segments on disk are slugified (lowercased, non-alphanumeric runs collapsed to "-").\n' >&2
  return 1
}

autofill_from_manifest() {
  if [[ -z "$PROJECT_ID" ]]; then
    return 0
  fi
  if [[ -n "$BRIEF_PATH" && -n "$TASK_TYPE" ]]; then
    return 0
  fi
  if [[ -z "$TASK_GROUP" || -z "$TASK_ID" ]]; then
    return 0
  fi

  # 신규 모델: PROJECT_ROOT 는 okstra.sh 가 시작 단계에서 best-effort 해석해 둔다.
  # 미해석(빈 문자열) 상태이거나 실제 디렉토리가 아니면 autofill 을 skip 한다 — 과거
  # "conf 파일 부재" 분기와 동일한 의미.
  if [[ -z "${PROJECT_ROOT:-}" || ! -d "${PROJECT_ROOT:-}" ]]; then
    return 0
  fi
  local manifest_project_root="$PROJECT_ROOT"

  local manifest_task_root=""
  manifest_task_root="$(resolve_task_root_for_shortcut "$manifest_project_root" "$PROJECT_ID" "$TASK_GROUP" "$TASK_ID" 2>/dev/null)" || return 0
  local manifest_path="$manifest_task_root/task-manifest.json"
  if [[ ! -f "$manifest_path" ]]; then
    return 0
  fi

  _okstra_interactive_cli reconcile-outcome \
    --project-root "$manifest_project_root" --task-root "$manifest_task_root" || true

  local autofill_output=""
  # autofill 은 편의 기능이라 실패해도 run 을 끊으면 안 된다. 모듈이 okstra_ctl 을
  # import 하므로 설치가 깨지면 비-0 으로 끝나는데, okstra.sh 는 `set -euo pipefail`
  # 이라 이 평범한 대입 하나가 run 을 통째로 중단시킨다. 위 reconcile 호출이 같은
  # 이유로 `|| true` 를 달고 있다.
  autofill_output="$(_okstra_interactive_cli autofill --manifest "$manifest_path" \
    $( [[ -z "$BRIEF_PATH" ]] && printf -- "--need-brief" ) \
    $( [[ -z "$TASK_TYPE" ]] && printf -- "--need-type" ))" || true

  local manifest_brief=""
  local manifest_type=""
  while IFS= read -r line; do
    case "$line" in
      BRIEF=*) manifest_brief="${line#BRIEF=}" ;;
      TYPE=*)   manifest_type="${line#TYPE=}" ;;
    esac
  done <<<"$autofill_output"

  if [[ -z "$TASK_TYPE" && -n "$manifest_type" ]]; then
    TASK_TYPE="$manifest_type"
    printf 'autofill: task-type from manifest workflow.nextRecommendedPhase: %s\n' "$TASK_TYPE" >&2
  fi
  # release-handoff 는 brief 입력이 없다 (prepare 가 검증 보고서 인용 input 을
  # 생성) — task-type autofill 이후에 판정해야 하므로 순서가 위와 바뀌면 안 된다.
  if [[ -z "$BRIEF_PATH" && -n "$manifest_brief" && "$TASK_TYPE" != "release-handoff" ]]; then
    BRIEF_PATH="$manifest_brief"
    printf 'autofill: brief-path from task-manifest.json: %s\n' "$BRIEF_PATH" >&2
  fi
}

missing_required_arguments_summary() {
  local missing=()

  [[ -z "$PROJECT_ID" ]] && missing+=("<project-id>")
  [[ -z "$TASK_GROUP" ]] && missing+=("<task-group>")
  [[ -z "$TASK_ID" ]] && missing+=("<task-id>")
  [[ -z "$TASK_TYPE" ]] && missing+=("<task-type>")
  # release-handoff 는 brief 입력이 없다 — prepare 가 input 문서를 생성한다.
  [[ -z "$BRIEF_PATH" && "$TASK_TYPE" != "release-handoff" ]] && missing+=("<brief-path>")

  if (( ${#missing[@]} == 0 )); then
    printf '%s' ""
    return 0
  fi

  printf '%s' "${missing[*]}"
}

prompt_for_required_argument() {
  local variable_name="$1"
  local prompt_label="$2"
  local current_value="${!variable_name}"

  current_value="$(trim_whitespace "$current_value")"

  while [[ -z "$current_value" ]]; do
    printf '%s: ' "$prompt_label" >&2
    if ! IFS= read -r current_value; then
      printf 'input cancelled while reading %s\n' "$prompt_label" >&2
      exit 1
    fi
    current_value="$(trim_whitespace "$current_value")"
  done

  printf -v "$variable_name" '%s' "$current_value"
}

find_latest_final_report() {
  # Args: project_root task_group task_id task_type_filter(optional)
  # Echoes: <abs path to latest final-report-*.md>\t<task-type>
  # Returns: 1 if not found.
  #
  # 선택 규칙(mtime 최신, 동률이면 basename)과 산출물 위치 지식은
  # okstra_ctl.paths.RunRef 가 정본이다. 과거 이 함수는 그 규칙을 bash 로
  # 재구현해 python 쪽과 손으로 동기화해야 했다.
  local project_root="$1"
  local task_group="$2"
  local task_id="$3"
  local task_type_filter="$4"

  # task-key 단축키 해소와 오타 진단(실제 task-key 목록 출력)은 이 resolver 가
  # 소유한다. 최신 보고서 선택만 python 정본에 위임한다.
  local task_root=""
  task_root="$(resolve_task_root_for_shortcut "$project_root" "$PROJECT_ID" "$task_group" "$task_id")" || {
    printf 'resume-clarification: unable to resolve task root for the given task-key. See diagnostics above.\n' >&2
    return 1
  }

  local found=""
  found="$(_okstra_interactive_cli latest-report \
    --task-root "$task_root" --task-type "$task_type_filter")" || return 1

  if [[ -z "$found" ]]; then
    printf 'resume-clarification: no final-report found for task %s:%s under %s/runs\n' \
      "$task_group" "$task_id" "$task_root" >&2
    return 1
  fi
  printf '%s\n' "$found"
}

run_resume_clarification() {
  if [[ "$RENDER_ONLY" == "true" ]]; then
    printf '%s\n' '--resume-clarification is incompatible with --render-only' >&2
    exit 1
  fi
  if [[ -n "${CLARIFICATION_RESPONSE_PATH-}" ]]; then
    printf '%s\n' '--resume-clarification is incompatible with --clarification-response (the resume mode supplies it automatically)' >&2
    exit 1
  fi
  if [[ -n "${APPROVED_PLAN_PATH-}" ]]; then
    printf '%s\n' '--resume-clarification is incompatible with --approved-plan' >&2
    exit 1
  fi

  if [[ -z "$PROJECT_ID" || -z "$TASK_GROUP" || -z "$TASK_ID" ]]; then
    printf 'resume-clarification: --project-id, --task-group, --task-id (or --task-key) are required\n' >&2
    exit 1
  fi

  # 신규 모델: PROJECT_ROOT 는 okstra.sh 진입 시점에 resolve_project_root_strict
  # 로 이미 확정되어 export 되어 있다.
  if [[ -z "${PROJECT_ROOT:-}" || ! -d "${PROJECT_ROOT:-}" ]]; then
    printf 'resume-clarification: PROJECT_ROOT not resolved\n' >&2
    exit 1
  fi
  local resume_project_root="$PROJECT_ROOT"

  local lookup_result=""
  if ! lookup_result="$(find_latest_final_report \
        "$resume_project_root" "$TASK_GROUP" "$TASK_ID" "${TASK_TYPE-}")"; then
    exit 1
  fi
  local report_path="${lookup_result%$'\t'*}"
  local resolved_type="${lookup_result##*$'\t'}"

  # implementation-planning 도 §1 Clarification Items(plan-body 결정: 예 C-205
  # tx-배관 step 누락)를 가지므로, 사용자가 결정란을 채운 뒤 같은 phase 를
  # clarification-response 자동공급으로 재실행해 plan 을 재생성·gate 재판정할 수
  # 있다. 자동검색(task_type_filter 없음)은 phase 디렉터리 전반에서 mtime 최신
  # 리포트를 고르므로 어느 phase 가 뽑힐지 보장되지 않는다. 따라서 이 경로는
  # --task-type implementation-planning 을 명시했을 때만 결정적으로 해소된다.
  case "$resolved_type" in
    requirements-discovery|error-analysis|implementation-planning) ;;
    *)
      printf '%s (resolved task-type: %s)\n' '--resume-clarification only applies to requirements-discovery, error-analysis, or implementation-planning runs' "$resolved_type" >&2
      exit 1
      ;;
  esac

  local resume_task_root=""
  resume_task_root="$(resolve_task_root_for_shortcut "$resume_project_root" "$PROJECT_ID" "$TASK_GROUP" "$TASK_ID")" || {
    printf 'resume-clarification: unable to resolve task root for the given task-key. See diagnostics above.\n' >&2
    exit 1
  }
  local manifest_file="$resume_task_root/task-manifest.json"
  if [[ ! -f "$manifest_file" ]]; then
    printf 'resume-clarification: task-manifest.json not found: %s\n' "$manifest_file" >&2
    exit 1
  fi
  local resume_brief_rel=""
  resume_brief_rel="$(_okstra_interactive_cli manifest-brief --manifest "$manifest_file")"
  if [[ -z "$resume_brief_rel" ]]; then
    printf 'resume-clarification: manifest missing taskBriefPath: %s\n' "$manifest_file" >&2
    exit 1
  fi

  # 직전 run 의 워커/모델/directive/related-tasks 를 그대로 이어 실행한다 — resume 가
  # 이 설정들을 안 넘기면 매 단계 재입력이 아니라 Python phase 기본값으로 조용히
  # 되돌아가 버린다. run-inputs 의 위치/구조 지식은 okstra_ctl.run_context 가 SSOT.
  local resume_extra_args=()
  while IFS= read -r -d '' _arg; do
    resume_extra_args+=("$_arg")
  done < <(_okstra_interactive_cli resume-args \
    --project-root "$PROJECT_ROOT" --task-group "$TASK_GROUP" \
    --task-id "$TASK_ID" --task-type "$resolved_type")

  if [[ "${OKSTRA_RESUME_CLARIFICATION_DRY_RUN:-false}" == "true" ]]; then
    printf 'resume-clarification (dry-run):\n' >&2
    printf '  report: %s\n' "$report_path" >&2
    printf '  re-exec: bash %s --task-type %s --project-id %s --task-group %s --task-id %s --task-brief %s --clarification-response %s' \
      "$0" "$resolved_type" "$PROJECT_ID" "$TASK_GROUP" "$TASK_ID" "$resume_brief_rel" "$report_path" >&2
    if (( ${#resume_extra_args[@]} > 0 )); then
      printf ' %s' "${resume_extra_args[@]}" >&2
    fi
    printf '\n' >&2
    return 0
  fi

  local editor_cmd="${EDITOR:-vi}"
  printf 'resume-clarification: opening %s with %s\n' "$report_path" "$editor_cmd" >&2
  if ! "$editor_cmd" "$report_path"; then
    printf 'resume-clarification: editor exited non-zero; aborting\n' >&2
    exit 1
  fi

  printf 'resume-clarification: re-running okstra with --clarification-response\n' >&2
  exec bash "$0" \
    --task-type "$resolved_type" \
    --project-id "$PROJECT_ID" \
    --task-group "$TASK_GROUP" \
    --task-id "$TASK_ID" \
    --task-brief "$resume_brief_rel" \
    --clarification-response "$report_path" \
    ${resume_extra_args[@]+"${resume_extra_args[@]}"}
}
