#!/usr/bin/env bash
#
# ccc - Smart tmux wrapper for Claude Code
#
# Runs Claude Code inside tmux for terminal crash resilience.
# Sessions persist even if the terminal crashes or is closed.
#
# Usage:
#   ccc             # Smart attach-or-create for current directory
#   cccstatus       # Show session status for current directory
#   ccclist         # Show all sessions with directories
#   cccattach NAME  # Attach to specific session
#   ccctasks        # Show persisted tasks
#   cccreview       # LLM-analyze tasks (run after reboot)
#   cccresume [n]   # Show/resume reviewed tasks
#   ccckill [NAME]  # Kill session (current dir if NAME omitted)
#   cccnew          # Force create new session
#   ccchelp         # Show help
#
set -euo pipefail

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
GRAY='\033[0;90m'
NC='\033[0m'

TASKS_DIR="$HOME/.local/claude/tasks"
REVIEWS_DIR="$HOME/.local/claude/reviews"
YELLOW='\033[0;33m'

check_dependencies() {
  if ! command -v tmux &>/dev/null; then
    echo -e "${RED}Error: tmux is not installed${NC}"
    exit 1
  fi
  if ! command -v claude &>/dev/null; then
    echo -e "${RED}Error: claude is not installed${NC}"
    exit 1
  fi
}

generate_session_name() {
  local dir="${1:-$(pwd)}"
  local hash=$(echo "$dir" | md5sum | cut -c1-4)
  local last_component=$(basename "$dir")
  # Sanitize for tmux (no dots, limited special chars)
  last_component=$(echo "$last_component" | tr '.' '-' | tr -cd '[:alnum:]-@_')
  echo "claude-${hash}-${last_component}"
}

session_exists() {
  tmux has-session -t "$1" 2>/dev/null
}

show_session_info() {
  local session="$1"
  local info=$(tmux list-sessions -F "#{session_name}|#{session_created_string}" 2>/dev/null | grep "^${session}|" || true)
  if [[ -n "$info" ]]; then
    local created=$(echo "$info" | cut -d'|' -f2)
    echo -e "  ${GRAY}Created: $created${NC}"
  fi
}

create_session() {
  local dir="$1"
  local session_name="$2"

  # Create detached session in target directory
  tmux new-session -d -s "$session_name" -c "$dir"

  # Store the original directory as session environment variable
  tmux set-environment -t "$session_name" CC_DIR "$dir"

  # Configure for Claude Code
  tmux set-option -t "$session_name" default-terminal "tmux-256color"
  tmux set-option -t "$session_name" mouse on

  # Start claude
  tmux send-keys -t "$session_name" "claude" Enter

  # Attach
  tmux attach-session -t "$session_name"
}

get_session_dir() {
  local session="$1"
  tmux show-environment -t "$session" CC_DIR 2>/dev/null | cut -d'=' -f2- || echo ""
}

get_session_prompt() {
  local dir="$1"
  [[ -z "$dir" ]] && return

  # Extract last component for simpler matching (e.g., @packages)
  local last_component=$(basename "$dir")

  # Find most recent task file matching this directory component
  local task_file=$(ls -t "$TASKS_DIR"/*"${last_component}"*.txt 2>/dev/null | head -1)
  [[ -z "$task_file" ]] && return

  # Extract prompt (lines after the blank line, first 50 chars)
  local prompt=$(awk '/^$/{found=1; next} found{print; exit}' "$task_file" 2>/dev/null)
  echo "${prompt:0:50}"
}

smart_attach() {
  local dir="${1:-$(pwd)}"
  local session_name=$(generate_session_name "$dir")

  if session_exists "$session_name"; then
    echo -e "${GREEN}Attaching to existing session:${NC} $session_name"
    show_session_info "$session_name"
    tmux attach-session -t "$session_name"
  else
    echo -e "${BLUE}Creating new session:${NC} $session_name"
    create_session "$dir" "$session_name"
  fi
}

list_sessions() {
  echo -e "${BLUE}=== Claude Code Sessions ===${NC}"
  echo ""

  local sessions=$(tmux list-sessions -F "#{session_name}|#{session_created_string}" 2>/dev/null | grep "^claude-" || true)
  local current_session=$(generate_session_name "$(pwd)")

  if [[ -z "$sessions" ]]; then
    echo "No claude sessions found."
    echo ""
    echo -e "${GRAY}Current directory: $(pwd)${NC}"
    echo -e "${GRAY}Would create: $current_session${NC}"
    return 0
  fi

  echo "$sessions" | while IFS='|' read -r name created; do
    local dir=$(get_session_dir "$name")
    local short_dir="${dir/#$HOME/~}"
    local prompt=$(get_session_prompt "$dir")
    local marker=" "
    local color=""

    # Highlight current directory's session
    if [[ "$name" == "$current_session" ]]; then
      marker="*"
      color="${GREEN}"
    fi

    # Show session with context
    printf "${color}%s %s${NC}\n" "$marker" "$name"
    printf "    ${GRAY}%s${NC}\n" "$short_dir"
    if [[ -n "$prompt" ]]; then
      printf "    ${GRAY}\"%s...\"${NC}\n" "$prompt"
    fi
    echo ""
  done

  echo -e "${GRAY}* = current directory${NC}"
}

show_tasks() {
  echo -e "${BLUE}=== Persisted Tasks ===${NC}"
  echo ""

  if [[ ! -d "$TASKS_DIR" ]] || [[ -z "$(ls -A "$TASKS_DIR" 2>/dev/null)" ]]; then
    echo "No persisted tasks found."
    return 0
  fi

  # Show most recent 10 tasks with prompts
  for task_file in $(ls -t "$TASKS_DIR"/*.txt 2>/dev/null | head -10); do
    [[ -f "$task_file" ]] || continue
    local basename=$(basename "$task_file" .txt)
    local timestamp=$(echo "$basename" | cut -d'_' -f1)
    local project=$(echo "$basename" | cut -d'_' -f2- | cut -d'-' -f1)
    local prompt=$(awk '/^$/{found=1; next} found{print; exit}' "$task_file" 2>/dev/null)

    # Convert timestamp to human-readable
    local date_str=$(date -d "@$((timestamp / 1000))" "+%m-%d %H:%M" 2>/dev/null || echo "$timestamp")

    echo -e "${GREEN}$project${NC} ${GRAY}($date_str)${NC}"
    if [[ -n "$prompt" ]]; then
      echo -e "  ${GRAY}\"${prompt:0:60}...\"${NC}"
    fi
    echo ""
  done
}

kill_session() {
  local target="$1"

  if [[ -z "$target" ]]; then
    target=$(generate_session_name)
  fi

  if session_exists "$target"; then
    tmux kill-session -t "$target"
    echo -e "${GREEN}Killed session:${NC} $target"
  else
    echo -e "${RED}Session not found:${NC} $target"
    return 1
  fi
}

review_tasks() {
  echo -e "${BLUE}=== Reviewing Tasks with LLM ===${NC}"
  echo ""

  mkdir -p "$REVIEWS_DIR"

  if [[ ! -d "$TASKS_DIR" ]] || [[ -z "$(ls -A "$TASKS_DIR" 2>/dev/null)" ]]; then
    echo "No tasks to review."
    return 0
  fi

  local task_files=$(ls -t "$TASKS_DIR"/*.txt 2>/dev/null | head -15)
  local count=0

  for task_file in $task_files; do
    [[ -f "$task_file" ]] || continue
    count=$((count + 1))

    local basename=$(basename "$task_file" .txt)
    local timestamp=$(echo "$basename" | cut -d'_' -f1)
    local project=$(echo "$basename" | cut -d'_' -f2- | cut -d'-' -f1)
    local review_file="$REVIEWS_DIR/${basename}.md"

    # Skip if recently reviewed (within last hour)
    if [[ -f "$review_file" ]]; then
      local review_age=$(( $(date +%s) - $(stat -c %Y "$review_file") ))
      if [[ $review_age -lt 3600 ]]; then
        echo -e "${GRAY}[$count] $project - already reviewed${NC}"
        continue
      fi
    fi

    echo -e "${YELLOW}[$count] Reviewing: $project...${NC}"

    # Read task content
    local task_content=$(cat "$task_file")

    # Get age in hours
    local now_ms=$(($(date +%s) * 1000))
    local age_hours=$(( (now_ms - timestamp) / 1000 / 3600 ))

    # Use Claude to analyze
    local review=$(claude --print -p "You are analyzing a saved task for session recovery. Be concise.

TASK FILE:
$task_content

TASK AGE: ${age_hours} hours

Analyze and respond with EXACTLY this format (no other text):

STATUS: [ACTIVE|COOLING|STALE]
- ACTIVE = recent (<4h) and incomplete work
- COOLING = paused work (4-24h) or waiting on something
- STALE = old (>24h) or completed work

SUMMARY: [1 sentence describing what was being worked on]

NEXT_STEP: [1 sentence describing what to do next to resume, or 'N/A' if complete]

DIRECTORY: [extract from task file]" 2>/dev/null || echo "STATUS: UNKNOWN
SUMMARY: Failed to analyze
NEXT_STEP: Review manually
DIRECTORY: unknown")

    # Save review
    cat > "$review_file" << EOF
# Task Review: $project
Generated: $(date -Iseconds)
Task ID: $timestamp

$review

---
Source: $task_file
EOF

    echo -e "${GREEN}  Done${NC}"
  done

  echo ""
  echo -e "Reviews saved to ${GRAY}$REVIEWS_DIR/${NC}"
  echo -e "Run ${BLUE}ccc resume${NC} to see results and resume a task"
}

show_reviews() {
  echo -e "${BLUE}=== Task Reviews ===${NC}"
  echo ""

  if [[ ! -d "$REVIEWS_DIR" ]] || [[ -z "$(ls -A "$REVIEWS_DIR" 2>/dev/null)" ]]; then
    echo "No reviews found. Run ${BLUE}ccc review${NC} first."
    return 0
  fi

  local index=0
  local active_tasks=()
  local cooling_tasks=()
  local stale_tasks=()

  # Categorize reviews
  for review_file in $(ls -t "$REVIEWS_DIR"/*.md 2>/dev/null); do
    [[ -f "$review_file" ]] || continue

    local status=$(grep "^STATUS:" "$review_file" | head -1 | cut -d: -f2 | tr -d ' ')
    local summary=$(grep "^SUMMARY:" "$review_file" | head -1 | cut -d: -f2-)
    local next_step=$(grep "^NEXT_STEP:" "$review_file" | head -1 | cut -d: -f2-)
    local directory=$(grep "^DIRECTORY:" "$review_file" | head -1 | cut -d: -f2- | tr -d ' ')
    local basename=$(basename "$review_file" .md)
    local project=$(echo "$basename" | cut -d'_' -f2- | cut -d'-' -f1)

    case "$status" in
      ACTIVE) active_tasks+=("$project|$summary|$next_step|$directory|$review_file") ;;
      COOLING) cooling_tasks+=("$project|$summary|$next_step|$directory|$review_file") ;;
      *) stale_tasks+=("$project|$summary|$next_step|$directory|$review_file") ;;
    esac
  done

  # Show active tasks
  if [[ ${#active_tasks[@]} -gt 0 ]]; then
    echo -e "${GREEN}ACTIVE (resume immediately)${NC}"
    for task in "${active_tasks[@]}"; do
      index=$((index + 1))
      IFS='|' read -r project summary next_step directory file <<< "$task"
      echo -e "  ${GREEN}[$index]${NC} $project"
      echo -e "      ${GRAY}$summary${NC}"
      echo -e "      ${BLUE}Next:${NC}$next_step"
      echo ""
    done
  fi

  # Show cooling tasks
  if [[ ${#cooling_tasks[@]} -gt 0 ]]; then
    echo -e "${YELLOW}COOLING (can resume)${NC}"
    for task in "${cooling_tasks[@]}"; do
      index=$((index + 1))
      IFS='|' read -r project summary next_step directory file <<< "$task"
      echo -e "  ${YELLOW}[$index]${NC} $project"
      echo -e "      ${GRAY}$summary${NC}"
      echo ""
    done
  fi

  # Show stale count
  if [[ ${#stale_tasks[@]} -gt 0 ]]; then
    echo -e "${GRAY}STALE: ${#stale_tasks[@]} tasks (run 'ccc tasks' to see all)${NC}"
  fi

  echo ""
  echo -e "Resume with: ${BLUE}ccc resume <number>${NC}"
}

resume_task() {
  local selector="$1"

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

  # Build indexed list of reviews (same order as show_reviews)
  local all_tasks=()
  for review_file in $(ls -t "$REVIEWS_DIR"/*.md 2>/dev/null); do
    [[ -f "$review_file" ]] || continue

    local status=$(grep "^STATUS:" "$review_file" | head -1 | cut -d: -f2 | tr -d ' ')
    local basename=$(basename "$review_file" .md)
    local project=$(echo "$basename" | cut -d'_' -f2- | cut -d'-' -f1)

    # Order: ACTIVE first, then COOLING, then STALE
    case "$status" in
      ACTIVE) all_tasks=("$project|$review_file" "${all_tasks[@]}") ;;
      COOLING) all_tasks+=("$project|$review_file") ;;
      *) all_tasks+=("$project|$review_file") ;;
    esac
  done

  local target_task=""

  # Check if selector is a number
  if [[ "$selector" =~ ^[0-9]+$ ]]; then
    local idx=$((selector - 1))
    if [[ $idx -ge 0 ]] && [[ $idx -lt ${#all_tasks[@]} ]]; then
      target_task="${all_tasks[$idx]}"
    fi
  else
    # Search by project name
    for task in "${all_tasks[@]}"; do
      local project=$(echo "$task" | cut -d'|' -f1)
      if [[ "$project" == *"$selector"* ]]; then
        target_task="$task"
        break
      fi
    done
  fi

  if [[ -z "$target_task" ]]; then
    echo -e "${RED}Task not found: $selector${NC}"
    echo "Run ${BLUE}ccc resume${NC} to see available tasks"
    return 1
  fi

  IFS='|' read -r project review_file <<< "$target_task"

  # Extract directory from the original task file
  local task_basename=$(basename "$review_file" .md)
  local task_file="$TASKS_DIR/${task_basename}.txt"
  local directory=""

  if [[ -f "$task_file" ]]; then
    directory=$(grep "^\[Directory:" "$task_file" | head -1 | sed 's/\[Directory: \(.*\)\]/\1/')
  fi

  if [[ -z "$directory" ]] || [[ ! -d "$directory" ]]; then
    echo -e "${RED}Directory not found: $directory${NC}"
    return 1
  fi

  # Extract review content
  local summary=$(grep "^SUMMARY:" "$review_file" | head -1 | cut -d: -f2-)
  local next_step=$(grep "^NEXT_STEP:" "$review_file" | head -1 | cut -d: -f2-)
  local status=$(grep "^STATUS:" "$review_file" | head -1 | cut -d: -f2 | tr -d ' ')

  # Read original task content for context
  local original_prompt=$(awk '/^$/{found=1; next} found && !/^---/{print}' "$task_file" 2>/dev/null | head -20)

  # Create handoff file in project directory
  local handoff_dir="$directory/.claude/handoffs"
  local handoff_timestamp=$(date +%Y%m%d_%H%M%S)
  local handoff_name=$(echo "$project" | tr -cd '[:alnum:]-_')
  local handoff_file="$handoff_dir/${handoff_timestamp}_${handoff_name}.md"

  mkdir -p "$handoff_dir"

  cat > "$handoff_file" << EOF
# Session Handoff: $project

**Status**: $status
**Generated**: $(date -Iseconds)
**Directory**: $directory

## Context
$summary

## What Was Being Worked On
$original_prompt

## Next Step
$next_step

## Instructions
Continue the work described above. The previous session ended unexpectedly (system crash/reboot).
Pick up where we left off based on the context provided.
EOF

  echo -e "${GREEN}=== Handoff Created ===${NC}"
  echo ""
  echo -e "Project:   ${BLUE}$project${NC}"
  echo -e "Directory: ${GRAY}$directory${NC}"
  echo -e "Status:    $status"
  echo ""
  echo -e "Context:  $summary"
  echo -e "Next:     $next_step"
  echo ""
  echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
  echo ""
  echo -e "To resume, run these commands:"
  echo ""
  echo -e "  ${GREEN}cd $directory${NC}"
  echo -e "  ${GREEN}ccc${NC}"
  echo ""
  echo -e "Then paste this into Claude:"
  echo ""
  echo -e "  ${BLUE}Read the handoff at .claude/handoffs/${handoff_timestamp}_${handoff_name}.md and continue the work${NC}"
  echo ""
  echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"

  # Copy the instruction to clipboard if xclip available
  if command -v xclip &>/dev/null; then
    echo "Read the handoff at .claude/handoffs/${handoff_timestamp}_${handoff_name}.md and continue the work" | xclip -selection clipboard
    echo ""
    echo -e "${GREEN}(Instruction copied to clipboard)${NC}"
  fi
}

show_status() {
  local dir="$(pwd)"
  local session_name=$(generate_session_name "$dir")
  local short_dir="${dir/#$HOME/~}"
  local prompt=$(get_session_prompt "$dir")

  echo -e "${BLUE}=== Current Directory ===${NC}"
  echo -e "  Path:    $short_dir"
  echo -e "  Session: $session_name"
  if [[ -n "$prompt" ]]; then
    echo -e "  Task:    \"$prompt...\""
  fi
  echo ""

  if session_exists "$session_name"; then
    local info=$(tmux list-sessions -F "#{session_name}|#{session_created_string}|#{session_activity_string}" 2>/dev/null | grep "^${session_name}|" || true)
    if [[ -n "$info" ]]; then
      local created=$(echo "$info" | cut -d'|' -f2)
      local activity=$(echo "$info" | cut -d'|' -f3)
      echo -e "${GREEN}Session running${NC}"
      echo -e "  Created:  $created"
      echo -e "  Activity: $activity"
      echo ""
      echo -e "Run ${BLUE}ccc${NC} to attach"
    fi
  else
    echo -e "${GRAY}No active session${NC}"
    echo ""
    echo -e "Run ${BLUE}ccc${NC} to create"
  fi
}

show_help() {
  cat << 'EOF'
ccc - Smart tmux wrapper for Claude Code

USAGE:
  ccc [command] [args]

COMMANDS:
  (default)     Smart attach-or-create session for current directory
  status, s     Show session status for current directory
  list, ls      Show all claude tmux sessions with directories
  attach, a     Attach to session by name
  tasks, t      Show persisted tasks from ~/.local/claude/tasks/
  review, r     Use LLM to analyze and categorize all tasks
  resume [n]    Show reviewed tasks, or resume task by number/name
  kill, k       Kill session (by name, or current dir if omitted)
  new, n        Force create new session even if one exists
  help, -h      Show this help message

RECOVERY WORKFLOW (after reboot):
  ccc review             # LLM analyzes all tasks, categorizes them
  ccc resume             # Shows: ACTIVE, COOLING, STALE tasks
  ccc resume 1           # Creates handoff file, shows paste instruction

EXAMPLES:
  ccc                    # Start/attach claude for current project
  ccc status             # Check if session exists for this dir
  ccc list               # See all sessions with their directories
  ccc review             # Analyze tasks after system reboot
  ccc resume             # See reviewed tasks
  ccc resume 2           # Resume second task
  ccc resume @packages   # Resume by project name

KEYBINDINGS (in tmux):
  Ctrl+B D     Detach from session (keeps claude running)
  Ctrl+B [     Enter scroll mode (arrows to scroll, q to exit)

EOF
}

main() {
  check_dependencies

  local cmd="${1:-}"

  case "$cmd" in
    "")
      smart_attach "$(pwd)"
      ;;
    status|s)
      show_status
      ;;
    list|ls)
      list_sessions
      ;;
    attach|a)
      if [[ -n "${2:-}" ]]; then
        tmux attach-session -t "$2"
      else
        echo -e "${RED}Usage: ccc attach SESSION_NAME${NC}"
        exit 1
      fi
      ;;
    tasks|t)
      show_tasks
      ;;
    review|r)
      review_tasks
      ;;
    resume)
      resume_task "${2:-}"
      ;;
    kill|k)
      kill_session "${2:-}"
      ;;
    new|n)
      local session_name="$(generate_session_name)-$(date +%s)"
      create_session "$(pwd)" "$session_name"
      ;;
    help|-h|--help)
      show_help
      ;;
    *)
      echo -e "${RED}Unknown command:${NC} $cmd"
      show_help
      exit 1
      ;;
  esac
}

main "$@"
