# ─────────────────────────────────────────────────────────────
# Shypmate Makefile
#
# Works on macOS, Linux, and Windows (Git Bash / WSL).
# Requires: make, python3/python, docker
#
# Usage:
#   make setup                     First-time setup (venv + image)
#   make task-add T="Fix the bug"  Add a task
#   make work                      Launch next pending task
#   make dashboard                 Live dashboard
#   make review ID=dev-a1b2c3      Review an agent
#   make retry ID=dev-a1b2c3       Re-launch an agent
#   make help                      Show all commands
# ─────────────────────────────────────────────────────────────

SHELL := /bin/bash

# ── Paths ───────────────────────────────────────────────────

SHYPMATE_DIR := $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
PROJECT_ROOT := $(shell cd "$(SHYPMATE_DIR)/.." && pwd)
ENV_FILE := $(PROJECT_ROOT)/.env

# Detect system Python: try python3, then python, then shypmate.yml python_path
SHYPMATE_YML := $(PROJECT_ROOT)/shypmate.yml
_YAML_PYTHON := $(shell if [ -f "$(SHYPMATE_YML)" ]; then \
    grep -E '^\s*python_path\s*:' "$(SHYPMATE_YML)" 2>/dev/null | head -1 | sed 's/.*:\s*//;s/^"\(.*\)"$$/\1/;s/^'"'"'\(.*\)'"'"'$$/\1/'; \
fi)

_FOUND_PYTHON := $(shell command -v python3 2>/dev/null || command -v python 2>/dev/null)

ifdef _FOUND_PYTHON
    PYTHON_SYS := $(_FOUND_PYTHON)
else ifdef _YAML_PYTHON
    PYTHON_SYS := $(_YAML_PYTHON)
else
    PYTHON_SYS := $(error No Python found. Install Python 3.12+ or set python_path in shypmate.yml)
endif

# Detect OS for venv paths
ifeq ($(OS),Windows_NT)
    PYTHON_VENV := $(SHYPMATE_DIR)/.venv/Scripts/python.exe
    PIP_VENV := $(SHYPMATE_DIR)/.venv/Scripts/pip.exe
else
    PYTHON_VENV := $(SHYPMATE_DIR)/.venv/bin/python
    PIP_VENV := $(SHYPMATE_DIR)/.venv/bin/pip
endif

# CLI prefix — load .env, then call the venv python directly (no activate needed)
CLI = set -a && [ -f "$(ENV_FILE)" ] && . "$(ENV_FILE)" || true && set +a && \
      cd "$(PROJECT_ROOT)" && "$(PYTHON_VENV)" -m shypmate

# Docker images
AGENT_IMAGE := shypmate-agent:latest
MONITOR_IMAGE := shypmate-monitor:latest

# Default values for optional args
P ?= normal
N ?= 50
INTERVAL ?= 60

# ─────────────────────────────────────────────────────────────
# Setup
# ─────────────────────────────────────────────────────────────

.PHONY: setup venv build build-monitor build-all

## First-time setup: create venv, install deps, build Docker image
setup: venv build
	@echo ""
	@echo "[shypmate] Setup complete. Run 'make help' to see available commands."

## Create/update the shypmate virtual environment
venv:
	@if [ ! -f "$(PYTHON_VENV)" ]; then \
		echo "[shypmate] Creating virtual environment..."; \
		$(PYTHON_SYS) -m venv "$(SHYPMATE_DIR)/.venv"; \
		"$(PIP_VENV)" install --upgrade pip --quiet; \
		"$(PIP_VENV)" install -r "$(SHYPMATE_DIR)/src/requirements.txt" --quiet; \
		echo "[shypmate] Virtual environment ready."; \
	else \
		echo "[shypmate] Virtual environment already exists."; \
	fi

## Build the agent Docker image
build:
	docker build -t $(AGENT_IMAGE) "$(SHYPMATE_DIR)/src"


## Build the PR monitor Docker image
build-monitor:
	docker build -t $(MONITOR_IMAGE) -f "$(SHYPMATE_DIR)/src/monitor/Dockerfile" "$(SHYPMATE_DIR)/src/monitor"

## Build both images
build-all: build build-monitor

# ─────────────────────────────────────────────────────────────
# Testing
# ─────────────────────────────────────────────────────────────

.PHONY: test-loop test-loop-live

## Run agent loop test with mock LLM (no API key needed)
test-loop:
	@"$(PYTHON_VENV)" "$(SHYPMATE_DIR)/tests/run_loop_test.py" -v

## Run agent loop test with real LLM (requires ANTHROPIC_API_KEY)
test-loop-live:
	@set -a && [ -f "$(ENV_FILE)" ] && . "$(ENV_FILE)" || true && set +a && \
	"$(PYTHON_VENV)" "$(SHYPMATE_DIR)/tests/run_loop_test.py" --live -v

# Note: tests/ stays at repo root, not inside src/

# ─────────────────────────────────────────────────────────────
# Task Management
# ─────────────────────────────────────────────────────────────

.PHONY: task-add task-list task-remove task-update work work-all

## Add a task: make task-add T="description" [P=high]
task-add:
ifndef T
	$(error Usage: make task-add T="task description" [P=critical|high|normal|low])
endif
	@$(CLI) task add "$(T)" --priority $(P)

## List pending/running tasks
task-list:
	@$(CLI) task list

## List ALL tasks (including done/failed)
task-list-all:
	@$(CLI) task list --all

## Remove a task: make task-remove ID=task-id
task-remove:
ifndef ID
	$(error Usage: make task-remove ID=task-id)
endif
	@$(CLI) task remove $(ID)

## Update a task: make task-update ID=task-id [P=priority] [S=status]
task-update:
ifndef ID
	$(error Usage: make task-update ID=task-id [P=priority] [S=status])
endif
	@$(CLI) task update $(ID) $(if $(P),--priority $(P)) $(if $(S),--status $(S))

## Launch the next pending task (by priority)
work:
	@$(CLI) work

## Launch all pending tasks
work-all:
	@$(CLI) work --all

## Launch top N tasks: make work-n N=3
work-n:
	@$(CLI) work -n $(N)

## Launch next task in foreground (watch output live)
work-live:
	@$(CLI) work --no-detach

# ─────────────────────────────────────────────────────────────
# Agent Lifecycle
# ─────────────────────────────────────────────────────────────

.PHONY: review retry logs clean status dashboard agent

## Review an agent: make review ID=dev-a1b2c3
review:
ifndef ID
	$(error Usage: make review ID=agent-id-or-task-id)
endif
	@$(CLI) review $(ID)

## Re-launch an agent: make retry ID=dev-a1b2c3
retry:
ifndef ID
	$(error Usage: make retry ID=agent-id-or-task-id)
endif
	@$(CLI) retry $(ID)

## Re-launch an agent in foreground: make retry-live ID=dev-a1b2c3
retry-live:
ifndef ID
	$(error Usage: make retry-live ID=agent-id-or-task-id)
endif
	@$(CLI) retry $(ID) --no-detach

## Show agent logs: make logs ID=dev-a1b2c3 [N=50]
logs:
ifndef ID
	$(error Usage: make logs ID=agent-id [N=lines])
endif
	@$(CLI) logs $(ID) -n $(N)

## Follow agent logs live: make logs-follow ID=dev-a1b2c3
logs-follow:
ifndef ID
	$(error Usage: make logs-follow ID=agent-id)
endif
	@$(CLI) logs $(ID) -f

## Launch an agent directly (skip queue): make agent T="Fix the bug"
agent:
ifndef T
	$(error Usage: make agent T="task description")
endif
	@$(CLI) run-agent --task "$(T)"

## Launch an agent in foreground: make agent-live T="Fix the bug"
agent-live:
ifndef T
	$(error Usage: make agent-live T="task description")
endif
	@$(CLI) run-agent --task "$(T)" --no-detach

## Show running containers
status:
	@docker ps --filter "name=shypmate" --format "table {{.Names}}\t{{.Status}}\t{{.Image}}\t{{.RunningFor}}"

## List all agent containers (including exited)
list-agents:
	@$(CLI) list-agents --all

## Live-updating dashboard
dashboard:
	@$(CLI) dashboard || true

## Remove containers for merged/closed PRs
clean:
	@$(CLI) clean

## Preview what clean would remove
clean-dry:
	@$(CLI) clean --dry-run

## Remove ALL exited agent containers
clean-all:
	@$(CLI) clean --all

## Sync task statuses with container/PR reality
sync:
	@$(CLI) sync

# ─────────────────────────────────────────────────────────────
# Session (start/stop your work day)
# ─────────────────────────────────────────────────────────────

.PHONY: start stop

## Start a work session: launch pending tasks + PR monitor
start:
	@echo "[shypmate] Starting work session..."
	@docker image inspect $(MONITOR_IMAGE) > /dev/null 2>&1 || \
		(echo "[shypmate] Building monitor image..." && \
		docker build -t $(MONITOR_IMAGE) -f "$(SHYPMATE_DIR)/src/monitor/Dockerfile" "$(SHYPMATE_DIR)/src/monitor")
	@$(CLI) work --all || true
	@$(CLI) monitor-start --interval $(INTERVAL)
	@echo ""
	@echo "[shypmate] Session active. Monitor polling every $(INTERVAL)s."
	@echo "  Run 'make dashboard' to watch progress."
	@echo "  Run 'make stop' when you're done for the day."

## Stop the work session: stop monitor + clean up merged containers
stop:
	@echo "[shypmate] Stopping work session..."
	@$(CLI) monitor-stop || true
	@$(CLI) clean || true
	@echo ""
	@echo "[shypmate] Session ended. Merged/closed PR containers cleaned up."
	@echo "  Running agents will finish their current work and exit."

# ─────────────────────────────────────────────────────────────
# Monitor
# ─────────────────────────────────────────────────────────────

.PHONY: monitor monitor-stop

## Start the PR monitor
monitor:
	@$(CLI) monitor-start --interval $(INTERVAL)

## Stop the PR monitor
monitor-stop:
	@$(CLI) monitor-stop

# ─────────────────────────────────────────────────────────────
# Help
# ─────────────────────────────────────────────────────────────

.PHONY: help

## Show this help
help:
	@echo ""
	@echo "shypmate — autonomous dev agent system"
	@echo ""
	@echo "Setup:"
	@echo "  make setup                          First-time setup (venv + Docker image)"
	@echo "  make venv                           Create/update virtual environment"
	@echo "  make build                          Build agent Docker image"
	@echo "  make build-monitor                  Build PR monitor image"
	@echo ""
	@echo "Task Management:"
	@echo "  make task-add T=\"desc\" [P=high]      Add a task (P: critical|high|normal|low)"
	@echo "  make task-list                       List pending/running tasks"
	@echo "  make task-list-all                   List all tasks"
	@echo "  make task-remove ID=task-id          Remove a task"
	@echo "  make task-update ID=id [P=p] [S=s]   Update priority/status"
	@echo ""
	@echo "Work:"
	@echo "  make work                            Launch next pending task"
	@echo "  make work-all                        Launch all pending tasks"
	@echo "  make work-n N=3                      Launch top N tasks"
	@echo "  make work-live                       Launch next task in foreground"
	@echo ""
	@echo "Agent Lifecycle:"
	@echo "  make review ID=agent-id              Review agent's work"
	@echo "  make retry ID=agent-id               Re-launch agent with same context"
	@echo "  make retry-live ID=agent-id           Re-launch in foreground"
	@echo "  make logs ID=agent-id [N=50]         Show last N log lines"
	@echo "  make logs-follow ID=agent-id         Follow logs live"
	@echo "  make agent T=\"desc\"                  Launch agent directly (skip queue)"
	@echo "  make agent-live T=\"desc\"             Launch direct, foreground"
	@echo ""
	@echo "Monitoring:"
	@echo "  make status                          Show running containers"
	@echo "  make list-agents                     List all containers (incl. exited)"
	@echo "  make dashboard                       Live-updating dashboard"
	@echo ""
	@echo "Cleanup & Sync:"
	@echo "  make sync                            Sync task statuses with reality"
	@echo "  make clean                           Remove containers (merged PRs only)"
	@echo "  make clean-dry                       Preview what clean would remove"
	@echo "  make clean-all                       Remove ALL exited containers"
	@echo ""
	@echo "Session:"
	@echo "  make start                           Start work session (tasks + monitor)"
	@echo "  make stop                            Stop session (monitor + cleanup)"
	@echo ""
	@echo "Monitor:"
	@echo "  make monitor                         Start PR monitor"
	@echo "  make monitor-stop                    Stop PR monitor"
	@echo ""

.DEFAULT_GOAL := help
