#!/usr/bin/env bash
# =============================================================================
# disinto — CLI entry point for the disinto code factory
#
# Commands:
#   disinto init <repo-url> [options]   Bootstrap a new project
#   disinto status                      Show factory status
#
# Usage:
#   disinto init https://codeberg.org/user/repo
#   disinto init https://codeberg.org/user/repo --branch main --ci-id 3
#   disinto status
# =============================================================================
set -euo pipefail

FACTORY_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
source "${FACTORY_ROOT}/lib/env.sh"

# ── Helpers ──────────────────────────────────────────────────────────────────

usage() {
  cat <<EOF
disinto — autonomous code factory CLI

Usage:
  disinto init <repo-url> [options]    Bootstrap a new project
  disinto status                       Show factory status

Init options:
  --branch <name>      Primary branch (default: auto-detect)
  --repo-root <path>   Local clone path (default: ~/name)
  --ci-id <n>          Woodpecker CI repo ID (default: 0 = no CI)
  --yes                Skip confirmation prompts
EOF
  exit 1
}

# Extract org/repo slug from various URL formats.
# Accepts: https://codeberg.org/user/repo, codeberg.org/user/repo,
#          user/repo, https://codeberg.org/user/repo.git
parse_repo_slug() {
  local url="$1"
  url="${url#https://}"
  url="${url#http://}"
  url="${url#codeberg.org/}"
  url="${url%.git}"
  url="${url%/}"
  if [[ ! "$url" =~ ^[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+$ ]]; then
    echo "Error: invalid repo URL — expected https://codeberg.org/org/repo or org/repo" >&2
    exit 1
  fi
  printf '%s' "$url"
}

# Build a clone-able URL from a slug.
clone_url_from_slug() {
  printf 'https://codeberg.org/%s.git' "$1"
}

# Validate that required tokens and tools are available.
validate_env() {
  local errors=0
  if [ -z "${CODEBERG_TOKEN:-}" ]; then
    echo "Error: CODEBERG_TOKEN is not set" >&2
    echo "  Set it in ${FACTORY_ROOT}/.env or export it" >&2
    errors=1
  fi
  if ! command -v claude &>/dev/null; then
    echo "Warning: claude CLI not found in PATH" >&2
  fi
  if [ "$errors" -gt 0 ]; then
    exit 1
  fi
}

# Clone the repo if the target directory doesn't exist; validate if it does.
clone_or_validate() {
  local slug="$1" target="$2"
  if [ -d "${target}/.git" ]; then
    echo "Repo:    ${target} (existing clone)"
    return
  fi
  local url
  url=$(clone_url_from_slug "$slug")
  echo "Cloning: ${url} -> ${target}"
  git clone "$url" "$target"
}

# Detect the primary branch from the remote HEAD or fallback to main/master.
detect_branch() {
  local repo_root="$1"
  local branch
  branch=$(git -C "$repo_root" symbolic-ref refs/remotes/origin/HEAD 2>/dev/null \
    | sed 's|refs/remotes/origin/||') || true
  if [ -z "$branch" ]; then
    if git -C "$repo_root" show-ref --verify --quiet refs/remotes/origin/main 2>/dev/null; then
      branch="main"
    else
      branch="master"
    fi
  fi
  printf '%s' "$branch"
}

# Generate projects/<name>.toml config file.
generate_toml() {
  local path="$1" name="$2" repo="$3" root="$4" branch="$5" ci_id="$6"
  cat > "$path" <<EOF
# projects/${name}.toml — Project config for ${repo}
#
# Generated by disinto init

name            = "${name}"
repo            = "${repo}"
repo_root       = "${root}"
primary_branch  = "${branch}"

[ci]
woodpecker_repo_id = ${ci_id}
stale_minutes      = 60

[services]
containers = []

[monitoring]
check_prs            = true
check_dev_agent      = true
check_pipeline_stall = false
EOF
}

# Create standard labels on the Codeberg repo.
create_labels() {
  local repo="$1"
  local api="https://codeberg.org/api/v1/repos/${repo}"

  local -A labels=(
    ["backlog"]="#0075ca"
    ["in-progress"]="#e4e669"
    ["blocked"]="#d73a4a"
    ["tech-debt"]="#cfd3d7"
    ["underspecified"]="#fbca04"
    ["vision"]="#0e8a16"
    ["action"]="#1d76db"
  )

  echo "Creating labels on ${repo}..."
  local name color
  for name in backlog in-progress blocked tech-debt underspecified vision action; do
    color="${labels[$name]}"
    if curl -sf -X POST \
      -H "Authorization: token ${CODEBERG_TOKEN}" \
      -H "Content-Type: application/json" \
      "${api}/labels" \
      -d "{\"name\":\"${name}\",\"color\":\"${color}\"}" >/dev/null 2>&1; then
      echo "  + ${name}"
    else
      echo "  . ${name} (already exists)"
    fi
  done
}

# Generate a minimal VISION.md template in the target project.
generate_vision() {
  local repo_root="$1" name="$2"
  local vision_path="${repo_root}/VISION.md"
  if [ -f "$vision_path" ]; then
    echo "VISION:  ${vision_path} (already exists, skipping)"
    return
  fi
  cat > "$vision_path" <<EOF
# Vision

## What ${name} does

<!-- Describe the purpose of this project in one paragraph -->

## Who it's for

<!-- Describe the target audience -->

## Design principles

- <!-- Principle 1 -->
- <!-- Principle 2 -->
- <!-- Principle 3 -->

## Milestones

### Current
- <!-- What you're working on now -->

### Next
- <!-- What comes after -->
EOF
  echo "Created: ${vision_path}"
  echo "  Commit this to your repo when ready"
}

# Generate and optionally install cron entries for the project agents.
install_cron() {
  local name="$1" toml="$2" auto_yes="$3"

  # Use absolute path for the TOML in cron entries
  local abs_toml
  abs_toml="$(cd "$(dirname "$toml")" && pwd)/$(basename "$toml")"

  local cron_block
  cron_block="# disinto: ${name}
2,7,12,17,22,27,32,37,42,47,52,57 * * * * ${FACTORY_ROOT}/review/review-poll.sh ${abs_toml} >/dev/null 2>&1
4,9,14,19,24,29,34,39,44,49,54,59 * * * * ${FACTORY_ROOT}/dev/dev-poll.sh ${abs_toml} >/dev/null 2>&1
0 0,6,12,18 * * * cd ${FACTORY_ROOT} && bash gardener/gardener-run.sh ${abs_toml} >/dev/null 2>&1"

  echo ""
  echo "Cron entries to install:"
  echo "$cron_block"
  echo ""

  if [ "$auto_yes" = false ] && [ -t 0 ]; then
    read -rp "Install these cron entries? [y/N] " confirm
    if [[ ! "$confirm" =~ ^[Yy] ]]; then
      echo "Skipped cron install. Add manually with: crontab -e"
      return
    fi
  fi

  # Append to existing crontab
  { crontab -l 2>/dev/null || true; printf '%s\n' "$cron_block"; } | crontab -
  echo "Cron entries installed"
}

# ── init command ─────────────────────────────────────────────────────────────

disinto_init() {
  local repo_url="${1:-}"
  if [ -z "$repo_url" ]; then
    echo "Error: repo URL required" >&2
    echo "Usage: disinto init <repo-url>" >&2
    exit 1
  fi
  shift

  # Parse flags
  local branch="" repo_root="" ci_id="0" auto_yes=false
  while [ $# -gt 0 ]; do
    case "$1" in
      --branch)    branch="$2"; shift 2 ;;
      --repo-root) repo_root="$2"; shift 2 ;;
      --ci-id)     ci_id="$2"; shift 2 ;;
      --yes)       auto_yes=true; shift ;;
      *) echo "Unknown option: $1" >&2; exit 1 ;;
    esac
  done

  # Extract org/repo slug
  local codeberg_repo
  codeberg_repo=$(parse_repo_slug "$repo_url")
  local project_name="${codeberg_repo##*/}"
  local toml_path="${FACTORY_ROOT}/projects/${project_name}.toml"

  echo "=== disinto init ==="
  echo "Project: ${codeberg_repo}"
  echo "Name:    ${project_name}"

  # Check for existing config
  if [ -f "$toml_path" ]; then
    echo "Error: ${toml_path} already exists" >&2
    exit 1
  fi

  # Validate tokens
  validate_env

  # Determine repo root
  repo_root="${repo_root:-/home/${USER}/${project_name}}"

  # Clone or validate
  clone_or_validate "$codeberg_repo" "$repo_root"

  # Detect primary branch
  if [ -z "$branch" ]; then
    branch=$(detect_branch "$repo_root")
  fi
  echo "Branch:  ${branch}"

  # Prompt for CI ID if interactive and not already set via flag
  if [ "$ci_id" = "0" ] && [ "$auto_yes" = false ] && [ -t 0 ]; then
    read -rp "Woodpecker CI repo ID (0 to skip CI): " user_ci_id
    ci_id="${user_ci_id:-0}"
  fi

  # Generate project TOML
  generate_toml "$toml_path" "$project_name" "$codeberg_repo" "$repo_root" "$branch" "$ci_id"
  echo "Created: ${toml_path}"

  # Create labels on remote
  create_labels "$codeberg_repo"

  # Generate VISION.md template
  generate_vision "$repo_root" "$project_name"

  # Install cron jobs
  install_cron "$project_name" "$toml_path" "$auto_yes"

  echo ""
  echo "Done. Project ${project_name} is ready."
  echo "  Config:  ${toml_path}"
  echo "  Clone:   ${repo_root}"
  echo "  Run 'disinto status' to verify."
}

# ── status command ───────────────────────────────────────────────────────────

disinto_status() {
  local toml_dir="${FACTORY_ROOT}/projects"
  local found=false

  for toml in "${toml_dir}"/*.toml; do
    [ -f "$toml" ] || continue
    found=true

    # Parse name and repo from TOML
    local pname prepo
    pname=$(python3 -c "
import sys, tomllib
with open(sys.argv[1], 'rb') as f:
    print(tomllib.load(f)['name'])
" "$toml" 2>/dev/null) || continue
    prepo=$(python3 -c "
import sys, tomllib
with open(sys.argv[1], 'rb') as f:
    print(tomllib.load(f)['repo'])
" "$toml" 2>/dev/null) || continue

    echo "== ${pname} (${prepo}) =="

    # Active dev sessions
    local has_sessions=false
    for pf in /tmp/dev-session-"${pname}"-*.phase; do
      [ -f "$pf" ] || continue
      has_sessions=true
      local issue phase_line
      issue=$(basename "$pf" | sed "s/dev-session-${pname}-//;s/\.phase//")
      phase_line=$(head -1 "$pf" 2>/dev/null || echo "unknown")
      echo "  Session #${issue}: ${phase_line}"
    done
    if [ "$has_sessions" = false ]; then
      echo "  Sessions: none"
    fi

    # Backlog depth via API
    if [ -n "${CODEBERG_TOKEN:-}" ]; then
      local api="https://codeberg.org/api/v1/repos/${prepo}"
      local backlog_count pr_count

      backlog_count=$(curl -sf -I \
        -H "Authorization: token ${CODEBERG_TOKEN}" \
        "${api}/issues?state=open&labels=backlog&limit=1" 2>/dev/null \
        | grep -i 'x-total-count' | tr -d '\r' | awk '{print $2}') || backlog_count="?"
      echo "  Backlog: ${backlog_count:-0} issues"

      pr_count=$(curl -sf -I \
        -H "Authorization: token ${CODEBERG_TOKEN}" \
        "${api}/pulls?state=open&limit=1" 2>/dev/null \
        | grep -i 'x-total-count' | tr -d '\r' | awk '{print $2}') || pr_count="?"
      echo "  Open PRs: ${pr_count:-0}"
    else
      echo "  Backlog: (no CODEBERG_TOKEN)"
      echo "  Open PRs: (no CODEBERG_TOKEN)"
    fi

    echo ""
  done

  if [ "$found" = false ]; then
    echo "No projects configured."
    echo "Run 'disinto init <repo-url>' to get started."
  fi
}

# ── Main dispatch ────────────────────────────────────────────────────────────

case "${1:-}" in
  init)   shift; disinto_init "$@" ;;
  status) shift; disinto_status "$@" ;;
  -h|--help) usage ;;
  *)         usage ;;
esac
