#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────────
# D.intelligence Agent Corps — Skill Bundle Installer
# Version: 1.0.0
# ─────────────────────────────────────────────────────────────────
#
# Installs the D.intelligence Agent Corps skill bundle for
# Claude Code and/or Claude Desktop on any macOS/Linux device.
#
# Usage:
#   ./install.sh                    # Interactive mode
#   ./install.sh --all              # Install everything
#   ./install.sh --code-only        # Claude Code skills only
#   ./install.sh --desktop-only     # Claude Desktop skills only
#   ./install.sh --dry-run          # Preview without changes
#   ./install.sh --uninstall        # Remove installed skills
#
# Prerequisites:
#   - Python >= 3.12
#   - pip or uv (for Python dependencies)
#   - Claude Code or Claude Desktop installed
#   - Git (to clone the repository if not already present)
#
# ─────────────────────────────────────────────────────────────────

set -eu

# ── Constants ────────────────────────────────────────────────────

VERSION="1.0.0"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SKILLS_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
SHARED_DIR="$SCRIPT_DIR"

# Skill definitions: number|name|description
SKILLS=(
  "70|dintel-brand-guardian|Brand compliance review & content generation"
  "71|dintel-brand-editor|Brand-compliant copywriting & style evaluation"
  "72|dintel-doc-secretary|Document formatting, meeting notes, reports"
  "73|dintel-quotation-mgr|Quotation generation with multi-agent sub-system"
  "74|dintel-service-architect|Service scope design & module recommendation"
  "75|dintel-marketing-mgr|Marketing content pipeline management"
  "76|dintel-backoffice-mgr|Administrative operations, invoicing, contracts"
  "77|dintel-account-mgr|Client relationship management & monitoring"
  "88|dintel-skill-update|Cross-skill consistency management (meta-agent)"
)

# Color output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m' # No Color

# ── Helper Functions ─────────────────────────────────────────────

log_info()    { echo -e "${BLUE}[INFO]${NC} $*"; }
log_success() { echo -e "${GREEN}[OK]${NC}   $*"; }
log_warn()    { echo -e "${YELLOW}[WARN]${NC} $*"; }
log_error()   { echo -e "${RED}[ERR]${NC}  $*"; }
log_step()    { echo -e "\n${BOLD}${CYAN}── $* ──${NC}"; }

DRY_RUN=false
INSTALL_CODE=false
INSTALL_DESKTOP=false
UNINSTALL=false

# ── Platform Detection ───────────────────────────────────────────

detect_platform() {
  local os
  os="$(uname -s)"
  case "$os" in
    Darwin) PLATFORM="macos" ;;
    Linux)  PLATFORM="linux" ;;
    *)      log_error "Unsupported platform: $os"; exit 1 ;;
  esac
}

detect_claude_paths() {
  # Claude Code config
  CLAUDE_CODE_CONFIG="$HOME/.claude.json"
  CLAUDE_CODE_DIR="$HOME/.claude"

  # Claude Desktop config (platform-dependent)
  if [[ "$PLATFORM" == "macos" ]]; then
    CLAUDE_DESKTOP_CONFIG="$HOME/Library/Application Support/Claude/claude_desktop_config.json"
    CLAUDE_DESKTOP_DIR="$HOME/Library/Application Support/Claude"
  else
    CLAUDE_DESKTOP_CONFIG="$HOME/.config/Claude/claude_desktop_config.json"
    CLAUDE_DESKTOP_DIR="$HOME/.config/Claude"
  fi

  # Check which Claude products are installed
  HAS_CLAUDE_CODE=false
  HAS_CLAUDE_DESKTOP=false

  if command -v claude &>/dev/null || [[ -f "$CLAUDE_CODE_CONFIG" ]]; then
    HAS_CLAUDE_CODE=true
  fi
  if [[ -d "$CLAUDE_DESKTOP_DIR" ]]; then
    HAS_CLAUDE_DESKTOP=true
  fi
}

detect_python() {
  PYTHON_CMD=""
  for cmd in python3.13 python3.12 python3; do
    if command -v "$cmd" &>/dev/null; then
      local ver
      ver="$($cmd --version 2>&1 | grep -oE '[0-9]+\.[0-9]+')"
      local major minor
      major="${ver%%.*}"
      minor="${ver#*.}"
      if [[ "$major" -ge 3 && "$minor" -ge 12 ]]; then
        PYTHON_CMD="$cmd"
        PYTHON_VERSION="$ver"
        return
      fi
    fi
  done
  log_warn "Python >= 3.12 not found. Python utilities will not be installed."
}

detect_package_manager() {
  PKG_MGR=""
  if command -v uv &>/dev/null; then
    PKG_MGR="uv"
  elif command -v pip3 &>/dev/null; then
    PKG_MGR="pip3"
  elif command -v pip &>/dev/null; then
    PKG_MGR="pip"
  fi
}

# ── Parse Arguments ──────────────────────────────────────────────

parse_args() {
  while [[ $# -gt 0 ]]; do
    case "$1" in
      --all)
        INSTALL_CODE=true
        INSTALL_DESKTOP=true
        ;;
      --code-only)
        INSTALL_CODE=true
        ;;
      --desktop-only)
        INSTALL_DESKTOP=true
        ;;
      --dry-run)
        DRY_RUN=true
        ;;
      --uninstall)
        UNINSTALL=true
        ;;
      --help|-h)
        show_help
        exit 0
        ;;
      *)
        log_error "Unknown option: $1"
        show_help
        exit 1
        ;;
    esac
    shift
  done
}

show_help() {
  cat <<'HELP'

  D.intelligence Agent Corps — Skill Bundle Installer v1.0.0

  Usage:
    ./install.sh                    Interactive mode
    ./install.sh --all              Install for both Claude Code and Desktop
    ./install.sh --code-only        Claude Code only
    ./install.sh --desktop-only     Claude Desktop only
    ./install.sh --dry-run          Preview without making changes
    ./install.sh --uninstall        Remove installed skills

  Skills Included:
    #70  Brand Guardian        Brand compliance review
    #71  Brand Editor          Copywriting & style evaluation
    #72  Doc Secretary         Document formatting & reports
    #73  Quotation Manager     Quotation generation (multi-agent)
    #74  Service Architect     Service scope & module design
    #75  Marketing Manager     Content pipeline management
    #76  Back Office Manager   Admin, invoicing, contracts
    #77  Account Manager       Client relationship & monitoring
    #88  Skill Update          Cross-skill consistency (meta-agent)

  Shared Infrastructure:
    _dintel-shared/              Python package + reference docs

HELP
}

# ── Pre-flight Checks ────────────────────────────────────────────

preflight() {
  log_step "Pre-flight Checks"

  detect_platform
  log_info "Platform: $PLATFORM"

  detect_claude_paths
  if $HAS_CLAUDE_CODE; then
    log_success "Claude Code detected"
  else
    log_warn "Claude Code not detected"
  fi
  if $HAS_CLAUDE_DESKTOP; then
    log_success "Claude Desktop detected"
  else
    log_warn "Claude Desktop not detected"
  fi

  detect_python
  if [[ -n "$PYTHON_CMD" ]]; then
    log_success "Python $PYTHON_VERSION ($PYTHON_CMD)"
  fi

  detect_package_manager
  if [[ -n "$PKG_MGR" ]]; then
    log_success "Package manager: $PKG_MGR"
  else
    log_warn "No pip/uv found — skipping Python package install"
  fi

  # Verify skill directories exist
  local missing=0
  for entry in "${SKILLS[@]}"; do
    IFS='|' read -r num name desc <<< "$entry"
    local dir="$SKILLS_ROOT/${num}-${name}"
    if [[ ! -d "$dir" ]]; then
      log_error "Missing skill directory: ${num}-${name}/"
      ((missing++))
    fi
  done
  if [[ $missing -gt 0 ]]; then
    log_error "$missing skill directories not found. Is the repository complete?"
    exit 1
  fi
  log_success "All 9 skill directories present"

  # Verify shared infrastructure
  if [[ ! -f "$SHARED_DIR/pyproject.toml" ]]; then
    log_error "_dintel-shared/pyproject.toml not found"
    exit 1
  fi
  if [[ ! -f "$SHARED_DIR/src/dintel/brand.py" ]]; then
    log_error "_dintel-shared/src/dintel/brand.py not found"
    exit 1
  fi
  log_success "Shared infrastructure intact"
}

# ── Interactive Mode ─────────────────────────────────────────────

interactive_prompt() {
  if $INSTALL_CODE || $INSTALL_DESKTOP || $UNINSTALL; then
    return  # Already specified via flags
  fi

  echo ""
  echo -e "${BOLD}D.intelligence Agent Corps — Skill Bundle Installer v${VERSION}${NC}"
  echo ""
  echo "  Available targets:"
  if $HAS_CLAUDE_CODE; then
    echo -e "    ${GREEN}[1]${NC} Claude Code       (code/CLAUDE.md directives)"
  else
    echo -e "    ${RED}[1]${NC} Claude Code       (not detected)"
  fi
  if $HAS_CLAUDE_DESKTOP; then
    echo -e "    ${GREEN}[2]${NC} Claude Desktop    (desktop/SKILL.md skills)"
  else
    echo -e "    ${RED}[2]${NC} Claude Desktop    (not detected)"
  fi
  echo -e "    ${GREEN}[3]${NC} Both"
  echo ""

  read -rp "  Select target [1/2/3]: " choice
  case "$choice" in
    1) INSTALL_CODE=true ;;
    2) INSTALL_DESKTOP=true ;;
    3) INSTALL_CODE=true; INSTALL_DESKTOP=true ;;
    *)
      log_error "Invalid choice"
      exit 1
      ;;
  esac
}

# ── Install Python Environment ───────────────────────────────────

install_python_env() {
  if [[ -z "$PYTHON_CMD" || -z "$PKG_MGR" ]]; then
    log_warn "Skipping Python environment setup (missing Python or pip)"
    return
  fi

  log_step "Python Environment — _dintel-shared"

  local venv_dir="$SHARED_DIR/.venv"

  if $DRY_RUN; then
    log_info "[DRY-RUN] Would create venv at: $venv_dir"
    log_info "[DRY-RUN] Would install dintel package in editable mode"
    return
  fi

  # Create virtual environment if it doesn't exist
  if [[ ! -d "$venv_dir" ]]; then
    log_info "Creating virtual environment..."
    "$PYTHON_CMD" -m venv "$venv_dir"
    log_success "Virtual environment created at $venv_dir"
  else
    log_info "Virtual environment already exists"
  fi

  # Activate and install
  log_info "Installing dintel package (editable mode)..."
  "$venv_dir/bin/pip" install --quiet --upgrade pip
  "$venv_dir/bin/pip" install --quiet -e "$SHARED_DIR"
  log_success "dintel package installed"

  # Verify
  if "$venv_dir/bin/python" -c "from dintel.brand import BRAND_NAME; print(f'  Brand: {BRAND_NAME}')" 2>/dev/null; then
    log_success "Package verification passed"
  else
    log_error "Package verification failed"
    return 1
  fi
}

# ── Install Claude Code Skills ───────────────────────────────────

install_code_skills() {
  if ! $INSTALL_CODE; then return; fi

  log_step "Claude Code Skills (code/CLAUDE.md)"

  # Claude Code skills are activated by project CLAUDE.md includes.
  # We create a project-level CLAUDE.md fragment that includes all skills.

  local target_dir
  if [[ -t 0 ]]; then
    read -rp "  Service Package repo path [default: current dir]: " target_dir
  else
    target_dir=""
  fi
  target_dir="${target_dir:-$(pwd)}"

  # Resolve to absolute
  target_dir="$(cd "$target_dir" 2>/dev/null && pwd)" || {
    log_error "Invalid path: $target_dir"
    return 1
  }

  local claude_md="$target_dir/CLAUDE.md"
  local include_block=""

  # Generate include block for CLAUDE.md
  include_block+=$'\n'"# ── D.intelligence Agent Corps Skills ────────────────────────"$'\n'
  include_block+="# Auto-generated by _dintel-shared/install.sh v${VERSION}"$'\n'
  include_block+="# Skills are loaded from: ${SKILLS_ROOT}"$'\n'
  include_block+="#"$'\n'
  include_block+="# To activate a specific agent in Claude Code, reference its CLAUDE.md:"$'\n'

  for entry in "${SKILLS[@]}"; do
    IFS='|' read -r num name desc <<< "$entry"
    local skill_claude_md="$SKILLS_ROOT/${num}-${name}/code/CLAUDE.md"
    if [[ -f "$skill_claude_md" ]]; then
      include_block+="#   Agent #${num} (${name}): ${skill_claude_md}"$'\n'
    fi
  done
  include_block+="# ─────────────────────────────────────────────────────────────"$'\n'

  if $DRY_RUN; then
    log_info "[DRY-RUN] Would append agent index to: $claude_md"
    echo "$include_block"
    return
  fi

  # Create symlinks in the project for easy access
  local agents_dir="$target_dir/.claude-agents"
  mkdir -p "$agents_dir"

  for entry in "${SKILLS[@]}"; do
    IFS='|' read -r num name desc <<< "$entry"
    local src="$SKILLS_ROOT/${num}-${name}/code/CLAUDE.md"
    local dest="$agents_dir/${num}-${name}.md"
    if [[ -f "$src" ]]; then
      ln -sf "$src" "$dest"
      log_success "#${num} ${name} → symlinked"
    fi
  done

  # Symlink shared library
  ln -sf "$SHARED_DIR" "$agents_dir/_dintel-shared"
  log_success "_dintel-shared → symlinked"

  # Write a loader CLAUDE.md fragment
  cat > "$agents_dir/README.md" <<EOF
# D.intelligence Agent Corps — Claude Code

Symlinks to agent directives for Claude Code.
Generated by \`_dintel-shared/install.sh v${VERSION}\`.

## Agents

| # | Agent | Directive |
|---|-------|-----------|
EOF

  for entry in "${SKILLS[@]}"; do
    IFS='|' read -r num name desc <<< "$entry"
    echo "| ${num} | ${name} | \`${num}-${name}.md\` |" >> "$agents_dir/README.md"
  done

  cat >> "$agents_dir/README.md" <<EOF

## Usage

In Claude Code, reference an agent directive:
\`\`\`
Read .claude-agents/70-dintel-brand-guardian.md
\`\`\`

Or add to your project CLAUDE.md as an include.

## Shared Library

\`_dintel-shared/\` contains:
- \`src/dintel/brand.py\` — Brand constants, colors, service modules
- \`src/dintel/document.py\` — DOCX generation
- \`src/dintel/excel.py\` — Excel generation
- \`src/dintel/notion.py\` — Notion DB IDs
- \`references/\` — Brand guide, pricing, Notion schema, design system
EOF

  log_success "Agent index created at $agents_dir/"
  echo ""
  log_info "To use agents in Claude Code:"
  log_info "  1. cd $target_dir"
  log_info "  2. claude  (start Claude Code)"
  log_info "  3. Reference .claude-agents/XX-name.md in your prompts"
}

# ── Install Claude Desktop Skills ────────────────────────────────

install_desktop_skills() {
  if ! $INSTALL_DESKTOP; then return; fi

  log_step "Claude Desktop Skills (desktop/SKILL.md)"

  # Claude Desktop skills are stored as project knowledge files.
  # They are loaded when the user opens a project that includes them.

  local skills_target="$HOME/.claude/skills"

  if $DRY_RUN; then
    log_info "[DRY-RUN] Would create skill directory: $skills_target"
    for entry in "${SKILLS[@]}"; do
      IFS='|' read -r num name desc <<< "$entry"
      log_info "[DRY-RUN] Would symlink: ${num}-${name}/desktop/ → $skills_target/${num}-${name}/"
    done
    return
  fi

  mkdir -p "$skills_target"

  for entry in "${SKILLS[@]}"; do
    IFS='|' read -r num name desc <<< "$entry"
    local src="$SKILLS_ROOT/${num}-${name}/desktop"
    local dest="$skills_target/${name}"

    if [[ -d "$src" ]]; then
      # Remove existing symlink/dir if present
      rm -rf "$dest"
      ln -sf "$src" "$dest"
      log_success "#${num} ${name} → $dest"
    else
      log_warn "#${num} ${name}: no desktop/ directory"
    fi
  done

  # Symlink shared references
  ln -sf "$SHARED_DIR/references" "$skills_target/dintel-references"
  log_success "Shared references → $skills_target/dintel-references"

  # Create an index file
  cat > "$skills_target/dintel-index.md" <<EOF
# D.intelligence Agent Corps — Claude Desktop Skills

Installed by \`_dintel-shared/install.sh v${VERSION}\`.
Source: \`${SKILLS_ROOT}\`

## Available Skills

| # | Skill | Description |
|---|-------|-------------|
EOF

  for entry in "${SKILLS[@]}"; do
    IFS='|' read -r num name desc <<< "$entry"
    echo "| ${num} | ${name} | ${desc} |" >> "$skills_target/INDEX.md"
  done

  cat >> "$skills_target/INDEX.md" <<EOF

## Usage in Claude Desktop

Add skill files as Project Knowledge when creating a new Claude Desktop project:
1. Open Claude Desktop → Settings → Projects
2. Create or open a D.intelligence project
3. Skills are auto-discovered from \`~/.claude/skills/dintel-*/SKILL.md\`

## Shared References

\`dintel-references/\` contains:
- \`dintelligence_brand_guide.md\` — Writing style guide
- \`design-system-2025.md\` — Visual identity system
- \`pricing-reference.md\` — Service pricing tables
- \`notion-schema-reference.md\` — Notion database schemas
EOF

  log_success "Skill index created at $skills_target/INDEX.md"
  echo ""
  log_info "To use skills in Claude Desktop:"
  log_info "  1. Open Claude Desktop → Projects"
  log_info "  2. Skills are auto-registered as slash commands in Claude Code"
}

# ── Uninstall ────────────────────────────────────────────────────

uninstall() {
  log_step "Uninstalling D.intelligence Agent Corps"

  local skills_target="$HOME/.claude/skills"
  local venv_dir="$SHARED_DIR/.venv"

  if $DRY_RUN; then
    log_info "[DRY-RUN] Would remove: $skills_target"
    log_info "[DRY-RUN] Would remove: $venv_dir"
    return
  fi

  if [[ -d "$skills_target" ]]; then
    rm -rf "$skills_target"
    log_success "Removed $skills_target"
  else
    log_info "No Desktop skills installed"
  fi

  if [[ -d "$venv_dir" ]]; then
    rm -rf "$venv_dir"
    log_success "Removed Python venv at $venv_dir"
  else
    log_info "No Python venv found"
  fi

  # Check for .claude-agents symlinks
  # Don't auto-remove — user may have customized
  if [[ -d ".claude-agents" ]]; then
    log_warn "Found .claude-agents/ in current directory — remove manually if desired"
  fi

  log_success "Uninstall complete"
}

# ── Summary ──────────────────────────────────────────────────────

show_summary() {
  log_step "Installation Summary"

  echo ""
  echo -e "  ${BOLD}D.intelligence Agent Corps v${VERSION}${NC}"
  echo -e "  ─────────────────────────────────────────"
  echo ""

  if $INSTALL_CODE; then
    echo -e "  ${GREEN}✓${NC} Claude Code skills installed"
  fi
  if $INSTALL_DESKTOP; then
    echo -e "  ${GREEN}✓${NC} Claude Desktop skills installed"
  fi
  if [[ -n "$PYTHON_CMD" ]]; then
    echo -e "  ${GREEN}✓${NC} Python environment ready (dintel package)"
  fi

  echo ""
  echo -e "  ${BOLD}Agents:${NC}"
  for entry in "${SKILLS[@]}"; do
    IFS='|' read -r num name desc <<< "$entry"
    echo -e "    ${CYAN}#${num}${NC} ${name} — ${desc}"
  done

  echo ""
  echo -e "  ${BOLD}Shared Infrastructure:${NC}"
  echo -e "    ${CYAN}_dintel-shared/${NC}"
  echo "      src/dintel/{brand,document,excel,notion}.py"
  echo "      references/{brand_guide,pricing,notion_schema,design_system}"
  echo ""
  echo -e "  ${BOLD}Source:${NC} ${SKILLS_ROOT}"
  echo ""
}

# ── Main ─────────────────────────────────────────────────────────

main() {
  parse_args "$@"

  echo ""
  echo -e "${BOLD}╔══════════════════════════════════════════════════════════╗${NC}"
  echo -e "${BOLD}║     D.intelligence Agent Corps — Skill Installer        ║${NC}"
  echo -e "${BOLD}║     v${VERSION}  •  9 Agents + Shared Infrastructure        ║${NC}"
  echo -e "${BOLD}╚══════════════════════════════════════════════════════════╝${NC}"

  if $DRY_RUN; then
    echo -e "\n  ${YELLOW}── DRY RUN MODE — No changes will be made ──${NC}\n"
  fi

  # Pre-flight
  preflight

  if $UNINSTALL; then
    uninstall
    exit 0
  fi

  # Interactive selection if no flags
  interactive_prompt

  # Install steps
  install_python_env
  install_code_skills
  install_desktop_skills

  # Summary
  if ! $DRY_RUN; then
    show_summary
  fi
}

main "$@"
