#!/usr/bin/env zsh

# Standalone plan-build launcher. This file is intentionally sourceable so its
# command seams can be replaced by the test suite.

_plan_build_usage() {
  print -r -- "Usage: plan_build [--yolo] [--prompt] [--brainstorm | --writing-plan]
       plan_build --architect [--new] [--yolo]"
}

_plan_build_require_cli() {
  local binary="$1"
  local label="$2"
  local resolved

  resolved="$(command -v "$binary" 2>/dev/null)" || resolved=""
  if [[ -n "$resolved" && -x "$resolved" ]]; then
    return 0
  fi

  print -u2 -r -- "Error: ${label} ('${binary}') is not installed or not in your PATH."
  return 1
}

_plan_build_confirm_indexing() {
  local project_root="$1"
  local reply

  if ! (: </dev/tty) 2>/dev/null; then
    print -u2 -r -- "Notice: No interactive terminal available; enhancing without project indexing."
    return 1
  fi

  printf "Allow Auggie to index and use project context from '%s'? (y/N) " "$project_root" >/dev/tty
  if ! IFS= read -r reply </dev/tty; then
    print -u2 -r -- "\nNotice: Unable to read confirmation; enhancing without project indexing."
    return 1
  fi

  [[ "$reply" == (y|Y|yes|YES|Yes) ]]
}

_plan_build_parse_auggie_output() {
  local log_file="$1"
  local output_file="$2"

  perl -ne '
    s/\r$//;
    s/.*\r//;
    1 while s/[^\x08]\x08//g;
    s/\x08//g;
    s/\e\][^\a]*(?:\a|\e\\)//g;
    s/\e\[[0-?]*[ -\/]*[@-~]//g;
    next if /Script started on/ || /Script done on/;
    if (/^(?:✨\s*)?Enhanced prompt:\s*(.*)$/) {
      $capturing = 1;
      $output .= "$1\n" if length $1;
      next;
    }
    next unless $capturing;
    exit if /^🤖/ || /Tool call:/ || /Session terminated/;
    $output .= $_;
    END {
      $output =~ s/^\s*\n//;
      $output =~ s/\s+\z//;
      print "$output\n" if length $output;
    }
  ' "$log_file" >| "$output_file"
}

_plan_build_platform() {
  command uname -s
}

_plan_build_start_auggie_script() {
  local platform="$1" log_file="$2" workspace="$3" cache_dir="$4"
  local auth_file="$5" prompt_file="$6" use_project_context="$7"
  shift 7

  if [[ "$platform" == Darwin ]]; then
    command script -q -t 0 "$log_file" auggie "$@" </dev/null >/dev/null 2>&1 &
  else
    AUGGIE_WORKSPACE="$workspace" AUGGIE_CACHE_DIR="$cache_dir" \
    AUGGIE_AUTH_FILE="$auth_file" AUGGIE_PROMPT_FILE="$prompt_file" \
    AUGGIE_INDEXING="$use_project_context" \
      command script -q -f -e -O "$log_file" -c '
        if [ "$AUGGIE_INDEXING" = 1 ]; then
          exec auggie --print --enhance-prompt --workspace-root "$AUGGIE_WORKSPACE" --augment-cache-dir "$AUGGIE_CACHE_DIR" --augment-session-json "$AUGGIE_AUTH_FILE" --allow-indexing --wait-for-indexing --dont-save-session --instruction-file "$AUGGIE_PROMPT_FILE"
        else
          exec auggie --print --enhance-prompt --no-discover-workspaces --workspace-root "$AUGGIE_WORKSPACE" --augment-cache-dir "$AUGGIE_CACHE_DIR" --augment-session-json "$AUGGIE_AUTH_FILE" --dont-save-session --instruction-file "$AUGGIE_PROMPT_FILE"
        fi
      ' </dev/null >/dev/null 2>&1 &
  fi
  REPLY=$!
}

_plan_build_enhance_prompt() {
  emulate -L zsh
  setopt localtraps
  local prompt="$1"
  local output_file="$2"
  local run_dir prompt_file workspace cache_dir auth_file log_file parsed_file
  local project_root use_project_context timeout_seconds script_pid= waited child_status=0
  local -a auggie_args

  trap 'return 130' INT
  trap 'return 143' TERM
  trap 'return 129' HUP

  if [[ -z "$prompt" ]]; then
    print -u2 -r -- "Error: Prompt was empty."
    return 1
  fi
  if [[ ! -s "$HOME/.augment/session.json" ]]; then
    print -u2 -r -- "Error: Auggie session file not found. Run 'auggie login' first."
    return 1
  fi

  run_dir="$(mktemp -d "${TMPDIR:-/tmp}/plan-build-auggie.XXXXXX")" || return 1
  trap "rm -rf -- ${(q)run_dir}" EXIT
  prompt_file="$run_dir/prompt.txt"
  workspace="$run_dir/workspace"
  cache_dir="$run_dir/cache"
  auth_file="$HOME/.augment/session.json"
  log_file="$run_dir/auggie.log"
  parsed_file="$run_dir/enhanced.txt"
  mkdir -p "$workspace" "$cache_dir" || {
    return 1
  }
  print -r -- "$prompt" >| "$prompt_file" || return 1

  project_root="$(command git rev-parse --show-toplevel 2>/dev/null)" || project_root="$PWD"
  use_project_context=0
  timeout_seconds=90
  if _plan_build_confirm_indexing "$project_root"; then
    use_project_context=1
    timeout_seconds=300
    workspace="$project_root"
    cache_dir="$HOME/.augment"
    print -u2 -r -- "Indexing approved; enhancing with project context from '${project_root}'."
  else
    print -u2 -r -- "Enhancing without project indexing."
  fi

  auggie_args=(--print --enhance-prompt --workspace-root "$workspace"
    --augment-cache-dir "$cache_dir" --augment-session-json "$auth_file"
    --dont-save-session --instruction-file "$prompt_file")
  if (( use_project_context )); then
    auggie_args+=(--allow-indexing --wait-for-indexing)
  else
    auggie_args+=(--no-discover-workspaces)
  fi

  _plan_build_start_auggie_script "$(_plan_build_platform)" "$log_file" \
    "$workspace" "$cache_dir" "$auth_file" "$prompt_file" \
    "$use_project_context" "${auggie_args[@]}" || return 1
  script_pid="$REPLY"
  trap "kill ${(q)script_pid} >/dev/null 2>&1
        wait ${(q)script_pid} >/dev/null 2>&1
        rm -rf -- ${(q)run_dir}" EXIT
  waited=0
  while kill -0 "$script_pid" >/dev/null 2>&1; do
    if command grep -aq "🤖" "$log_file" 2>/dev/null ||
       command grep -aq "Tool call:" "$log_file" 2>/dev/null; then
      kill "$script_pid" >/dev/null 2>&1 || true
      wait "$script_pid" >/dev/null 2>&1 || true
      script_pid=
      trap "rm -rf -- ${(q)run_dir}" EXIT
      child_status=0
      break
    fi
    if (( waited >= timeout_seconds )); then
      kill "$script_pid" >/dev/null 2>&1 || true
      wait "$script_pid" >/dev/null 2>&1 || true
      script_pid=
      trap "rm -rf -- ${(q)run_dir}" EXIT
      print -u2 -r -- "Error: Timed out waiting for Auggie to enhance the prompt."
      return 124
    fi
    sleep 1
    waited=$((waited + 1))
  done
  if [[ -n "$script_pid" ]]; then
    wait "$script_pid"
    child_status=$?
    script_pid=
    trap "rm -rf -- ${(q)run_dir}" EXIT
  fi
  if (( child_status != 0 )); then
    print -u2 -r -- "Error: Auggie process failed with status ${child_status}."
    return "$child_status"
  fi

  _plan_build_parse_auggie_output "$log_file" "$parsed_file"
  if [[ ! -s "$parsed_file" ]]; then
    print -u2 -r -- "Error: Auggie did not return an enhanced prompt."
    return 1
  fi
  command cp "$parsed_file" "$output_file" || {
    print -u2 -r -- "Error: Unable to save the enhanced prompt."
    return 1
  }
}

_plan_build_confirm_enhanced_prompt() {
  local reply

  if ! (: </dev/tty) 2>/dev/null; then
    print -r -- "❌ Error: Cannot review the enhanced prompt without an interactive terminal; Claude was not launched."
    return 2
  fi
  printf "Proceed with this enhanced prompt? (y/N) " >/dev/tty
  if ! IFS= read -r reply </dev/tty; then
    printf '\n' >/dev/tty
    print -r -- "🛑 Review cancelled; Claude was not launched."
    return 2
  fi
  [[ "$reply" == (y|Y|yes|YES|Yes) ]]
}

_plan_build_superpowers_state() {
  awk '
    BEGIN { RS = "}"; state = "missing"; printed = 0 }
    /"id"[[:space:]]*:[[:space:]]*"superpowers@claude-plugins-official"/ {
      state = "installed"
      if ($0 ~ /"enabled"[[:space:]]*:[[:space:]]*true/) state = "enabled"
      else if ($0 ~ /"enabled"[[:space:]]*:[[:space:]]*false/) state = "disabled"
      print state
      printed = 1
      exit
    }
    END { if (!printed) print state }
  '
}

_plan_build_superpowers_preflight() {
  local plugin_json plugin_state

  case "${CLAUDE_CODE_SAFE_MODE:-}" in
    1|true|TRUE|yes|YES|on|ON)
      print -r -- "❌ Error: Claude Code safe mode disables Superpowers."
      print -r -- "Unset CLAUDE_CODE_SAFE_MODE before using --brainstorm or --writing-plan."
      return 1
      ;;
  esac
  if ! plugin_json="$(command claude plugin list --json 2>/dev/null)"; then
    print -r -- "❌ Error: Unable to inspect Claude Code plugins."
    print -r -- "Run 'claude plugin list' to diagnose the problem."
    return 1
  fi
  plugin_state="$(print -r -- "$plugin_json" | _plan_build_superpowers_state)"
  case "$plugin_state" in
    enabled) return 0 ;;
    disabled)
      print -r -- "❌ Error: Claude Code Superpowers is installed but disabled."
      print -r -- "Enable it with: claude plugin enable superpowers@claude-plugins-official"
      ;;
    missing)
      print -r -- "❌ Error: Claude Code Superpowers is required for --brainstorm and --writing-plan."
      print -r -- "Install it in Claude Code with: /plugin install superpowers@claude-plugins-official"
      ;;
    *)
      print -r -- "❌ Error: Unable to determine Claude Code Superpowers status."
      print -r -- "Run 'claude plugin list' to diagnose the problem."
      ;;
  esac
  return 1
}

_plan_build_is_worktree() {
  local inside_work_tree
  inside_work_tree="$(command git rev-parse --is-inside-work-tree 2>/dev/null)" || return 1
  [[ "$inside_work_tree" == true ]]
}

_plan_build_has_tty() {
  (: </dev/tty) 2>/dev/null
}

_plan_build_architect_preflight() {
  local skill_path="${PLAN_BUILD_ARCHITECT_SKILL_PATH:-$HOME/.claude/skills/plan-build-architect/SKILL.md}"

  if ! _plan_build_has_tty; then
    print -r -- "❌ Error: Architect mode requires an interactive terminal."
    print -r -- "Run plan_build --architect from an interactive terminal."
    return 1
  fi
  _plan_build_require_cli claude "Claude Code CLI" || return 1
  _plan_build_require_cli codex "Codex CLI" || return 1
  _plan_build_require_cli coderabbit "CodeRabbit CLI" || return 1
  _plan_build_require_cli git "Git CLI" || return 1
  if ! _plan_build_is_worktree; then
    print -r -- "❌ Error: Architect mode must run inside a Git worktree."
    print -r -- "Change to a Git worktree, then retry plan_build --architect."
    return 1
  fi
  if [[ ! -r "$skill_path" || ! -s "$skill_path" ]]; then
    print -r -- "❌ Error: Architect skill is missing, unreadable, or empty: $skill_path"
    print -r -- "Install a readable, non-empty plan-build-architect skill at that path."
    return 1
  fi
}

_plan_build_launch_claude() {
  local use_yolo="$1"
  shift
  if (( use_yolo )); then
    command claude --dangerously-skip-permissions "$@"
  else
    command claude "$@"
  fi
}

_plan_build_read_payload() {
  local line payload=""
  while IFS= read -r line; do
    [[ "$line" == EOF ]] && break
    if [[ -z "$payload" ]]; then
      payload="$line"
    else
      payload+=$'\n'"$line"
    fi
  done
  print -r -- "$payload"
}

plan_build() {
  emulate -L zsh
  setopt localtraps
  local use_yolo=0 use_architect=0 use_new=0 enhance_payload=0
  local planning_mode="standard"
  local payload enhanced_file= confirm_status enhance_status planning_instruction architect_start_mode
  local standard_skill="${PLAN_BUILD_SKILL_PATH:-$HOME/.claude/skills/plan-build/SKILL.md}"
  local architect_skill="${PLAN_BUILD_ARCHITECT_SKILL_PATH:-$HOME/.claude/skills/plan-build-architect/SKILL.md}"

  trap 'return 130' INT
  trap 'return 143' TERM
  trap 'return 129' HUP

  while (( $# )); do
    case "$1" in
      --yolo)
        (( use_yolo )) && {
          print -r -- "Error: Duplicate argument: --yolo"
          _plan_build_usage
          return 1
        }
        use_yolo=1
        ;;
      --architect)
        (( use_architect )) && {
          print -r -- "Error: Duplicate argument: --architect"
          _plan_build_usage
          return 1
        }
        use_architect=1
        ;;
      --new)
        (( use_new )) && {
          print -r -- "Error: Duplicate argument: --new"
          _plan_build_usage
          return 1
        }
        use_new=1
        ;;
      --prompt)
        (( enhance_payload )) && {
          print -r -- "Error: Duplicate argument: --prompt"
          _plan_build_usage
          return 1
        }
        enhance_payload=1
        ;;
      --brainstorm)
        [[ "$planning_mode" == brainstorm ]] && {
          print -r -- "Error: Duplicate argument: --brainstorm"
          _plan_build_usage
          return 1
        }
        [[ "$planning_mode" != standard ]] && {
          print -r -- "Error: --brainstorm and --writing-plan are mutually exclusive."
          _plan_build_usage
          return 1
        }
        planning_mode="brainstorm"
        ;;
      --writing-plan)
        [[ "$planning_mode" == writing-plan ]] && {
          print -r -- "Error: Duplicate argument: --writing-plan"
          _plan_build_usage
          return 1
        }
        [[ "$planning_mode" != standard ]] && {
          print -r -- "Error: --brainstorm and --writing-plan are mutually exclusive."
          _plan_build_usage
          return 1
        }
        planning_mode="writing-plan"
        ;;
      *)
        print -r -- "Error: Unknown argument: $1"
        _plan_build_usage
        return 1
        ;;
    esac
    shift
  done

  if (( use_new && ! use_architect )); then
    print -r -- "Error: --new requires --architect."
    _plan_build_usage
    return 1
  fi
  if (( use_architect && enhance_payload )) ||
     { (( use_architect )) && [[ "$planning_mode" != standard ]]; }; then
    print -r -- "Error: --architect may combine only with --new and --yolo."
    _plan_build_usage
    return 1
  fi

  if (( use_architect )); then
    _plan_build_architect_preflight || return 1
  else
    _plan_build_require_cli claude "Claude Code CLI" || return 1
    if [[ "$planning_mode" != standard ]]; then
      _plan_build_superpowers_preflight || return 1
    fi
    _plan_build_require_cli codex "Codex CLI" || return 1
    _plan_build_require_cli coderabbit "CodeRabbit CLI" || return 1
    if (( enhance_payload )); then
      _plan_build_require_cli auggie "Auggie CLI" || return 1
      _plan_build_require_cli script "script utility" || return 1
      _plan_build_require_cli perl "Perl" || return 1
    fi
  fi

  print -r -- "📥 Reading payload... Type 'EOF' on a new line and press Enter when finished."
  payload="$(_plan_build_read_payload)"
  if [[ -z "$payload" ]]; then
    print -r -- "❌ Error: Payload was empty."
    return 1
  fi

  if (( enhance_payload )); then
    enhanced_file="$(mktemp "${TMPDIR:-/tmp}/plan-build-enhanced.XXXXXX")" || return 1
    trap "rm -f -- ${(q)enhanced_file}" EXIT
    print -r -- "✨ Enhancing payload with Auggie..."
    _plan_build_enhance_prompt "$payload" "$enhanced_file"
    enhance_status=$?
    if (( enhance_status != 0 )); then
      print -r -- "❌ Error: Prompt enhancement failed; Claude was not launched."
      return "$enhance_status"
    fi
    payload="$(<"$enhanced_file")"
    rm -f -- "$enhanced_file"
    enhanced_file=
    trap - EXIT
    if [[ -z "$payload" ]]; then
      print -r -- "❌ Error: Enhanced payload was empty; Claude was not launched."
      return 1
    fi
    printf '\n%s\n%s\n%s\n\n' \
      "━━━━━━━━━━━━━━━━ Auggie enhanced prompt ━━━━━━━━━━━━━━━━" \
      "$payload" \
      "━━━━━━━━━━━━━━━━ End enhanced prompt ━━━━━━━━━━━━━━━━━"
    _plan_build_confirm_enhanced_prompt
    confirm_status=$?
    if (( confirm_status == 2 )); then
      return 1
    elif (( confirm_status != 0 )); then
      print -r -- "🛑 Enhanced prompt not approved; Claude was not launched."
      return 0
    fi
    print -r -- "✅ Enhanced prompt approved."
  fi

  if (( use_architect )); then
    if (( use_new )); then
      architect_start_mode="Start mode: archive-and-start-new. Explicitly archive the prior planning state as the skill directs, then begin a new architecture plan."
    else
      architect_start_mode="Start mode: safe-resume-detection. Safely detect whether an existing architecture planning session should be resumed; do not archive or replace it automatically."
    fi
    print -r -- "🚀 Launching Claude Code in architect mode..."
    _plan_build_launch_claude "$use_yolo" "Read \`$architect_skill\` and follow it strictly, including every gate even when permissive Claude execution is active. Stay in the documentation-first architect/orchestrator role: produce and coordinate documentation and planning only, and do not implement the requirement.

$architect_start_mode

Use the following payload as the initial requirement:

$payload"
    return $?
  fi

  case "$planning_mode" in
    brainstorm)
      planning_instruction="Planning mode: brainstorm. Use the superpowers:brainstorming skill, including its approval gates and transition to superpowers:writing-plans. After the implementation plan is saved, return to the plan-build workflow for Codex plan review before implementation."
      ;;
    writing-plan)
      planning_instruction="Planning mode: writing-plan. Use the superpowers:writing-plans skill with the payload as the requirements. After the implementation plan is saved, return to the plan-build workflow for Codex plan review before implementation."
      ;;
    *)
      planning_instruction="Planning mode: standard. Create the workflow's normal short implementation plan."
      ;;
  esac

  print -r -- "🚀 Launching Claude Code with your multi-agent workflow (${planning_mode} planning)..."
  _plan_build_launch_claude "$use_yolo" "Please read \`$standard_skill\` and strictly follow the 8-step multi-agent workflow to implement the following task.

$planning_instruction

$payload"
}

_plan_build_main() {
  plan_build "$@"
}

if [[ "${ZSH_EVAL_CONTEXT:-}" == toplevel ]]; then
  _plan_build_main "$@"
fi
