#!/bin/bash
# Gantt Board Complete CLI
# All API operations available to the web UI
# Usage: ./gantt.sh <command> [args]

set -e

# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
API_URL="${API_URL:-http://localhost:3000/api}"

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

# Helper functions
log_info() { echo -e "${BLUE}ℹ${NC} $1"; }
log_success() { echo -e "${GREEN}✓${NC} $1"; }
log_error() { echo -e "${RED}✗${NC} $1"; }
log_warn() { echo -e "${YELLOW}⚠${NC} $1"; }

# Check dependencies
check_deps() {
  if ! command -v jq &> /dev/null; then
    log_error "jq is required but not installed. Run: brew install jq"
    exit 1
  fi
  if ! command -v curl &> /dev/null; then
    log_error "curl is required but not installed"
    exit 1
  fi
}

# API call helper
api_call() {
  local method="$1"
  local endpoint="$2"
  local data="${3:-}"
  local url="${API_URL}${endpoint}"
  
  local curl_opts=(-s -w "\n%{http_code}" -H "Content-Type: application/json")
  
  if [ -n "$data" ]; then
    curl_opts+=(-d "$data")
  fi
  
  local response
  response=$(curl "${curl_opts[@]}" -X "$method" "$url")
  
  local http_code
  http_code=$(echo "$response" | tail -n1)
  local body
  body=$(echo "$response" | sed '$d')
  
  if [ "$http_code" -ge 200 ] && [ "$http_code" -lt 300 ]; then
    echo "$body"
    return 0
  else
    log_error "API call failed (HTTP $http_code)"
    echo "$body" | jq '.' 2>/dev/null || echo "$body"
    return 1
  fi
}

#===================
# TASK OPERATIONS
#===================

cmd_task_list() {
  local filter="${1:-}"
  log_info "Fetching tasks..."
  
  local response
  response=$(api_call GET "/tasks")
  
  if [ -n "$filter" ]; then
    echo "$response" | jq --arg status "$filter" '.tasks | map(select(.status == $status))'
  else
    echo "$response" | jq '.tasks'
  fi
}

cmd_task_get() {
  local task_id="$1"
  if [ -z "$task_id" ]; then
    log_error "Usage: task get <task-id>"
    exit 1
  fi
  
  log_info "Fetching task $task_id..."
  local response
  response=$(api_call GET "/tasks")
  echo "$response" | jq --arg id "$task_id" '.tasks | map(select(.id == $id)) | .[0]'
}

cmd_task_create() {
  local title="$1"
  local status="${2:-open}"
  local priority="${3:-medium}"
  local project_id="${4:-1}"
  
  if [ -z "$title" ]; then
    log_error "Usage: task create <title> [status] [priority] [project-id]"
    exit 1
  fi
  
  log_info "Creating task: $title"
  
  local task_json
  task_json=$(jq -n \
    --arg title "$title" \
    --arg status "$status" \
    --arg priority "$priority" \
    --arg projectId "$project_id" \
    '{
      title: $title,
      status: $status,
      priority: $priority,
      projectId: $projectId,
      type: "task",
      comments: [],
      tags: []
    }')
  
  api_call POST "/tasks" "{\"task\": $task_json}"
}

cmd_task_natural() {
  local text="$1"
  if [ -z "$text" ]; then
    log_error "Usage: task natural <text-description>"
    echo "Example: ./gantt.sh task natural \"Fix login bug by Friday, high priority\""
    exit 1
  fi
  
  log_info "Creating task from natural language..."
  api_call POST "/tasks/natural" "{\"text\": \"$text\"}"
}

cmd_task_update() {
  local task_id="$1"
  local field="$2"
  local value="$3"
  
  if [ -z "$task_id" ] || [ -z "$field" ]; then
    log_error "Usage: task update <task-id> <field> <value>"
    echo "Fields: status, priority, title, description, assigneeId, sprintId, dueDate"
    exit 1
  fi
  
  log_info "Updating task $task_id: $field = $value"
  
  # First get the task
  local response
  response=$(api_call GET "/tasks")
  
  local task
  task=$(echo "$response" | jq --arg id "$task_id" '.tasks | map(select(.id == $id)) | .[0]')
  
  if [ "$task" = "null" ] || [ -z "$task" ]; then
    log_error "Task not found: $task_id"
    exit 1
  fi
  
  # Update the field
  local updated_task
  updated_task=$(echo "$task" | jq --arg field "$field" --arg value "$value" '. + {($field): $value}')
  
  api_call POST "/tasks" "{\"task\": $updated_task}"
}

cmd_task_delete() {
  local task_id="$1"
  if [ -z "$task_id" ]; then
    log_error "Usage: task delete <task-id>"
    exit 1
  fi
  
  log_warn "Deleting task $task_id..."
  api_call DELETE "/tasks" "{\"id\": \"$task_id\"}"
}

cmd_task_comment() {
  local task_id="$1"
  local text="$2"
  
  if [ -z "$task_id" ] || [ -z "$text" ]; then
    log_error "Usage: task comment <task-id> <text>"
    exit 1
  fi
  
  log_info "Adding comment to task $task_id..."
  
  # Get current task
  local response
  response=$(api_call GET "/tasks")
  
  local task
  task=$(echo "$response" | jq --arg id "$task_id" '.tasks | map(select(.id == $id)) | .[0]')
  
  if [ "$task" = "null" ]; then
    log_error "Task not found: $task_id"
    exit 1
  fi
  
  # Add comment
  local comment_id
  comment_id=$(date +%s)
  local new_comment
  new_comment=$(jq -n \
    --arg id "$comment_id" \
    --arg text "$text" \
    --arg createdAt "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
    '{id: $id, text: $text, createdAt: $createdAt, author: "assistant"}')
  
  local updated_task
  updated_task=$(echo "$task" | jq --argjson comment "$new_comment" '.comments += [$comment]')
  
  api_call POST "/tasks" "{\"task\": $updated_task}"
}

cmd_task_attach() {
  local task_id="$1"
  local file_path="$2"
  
  if [ -z "$task_id" ] || [ -z "$file_path" ]; then
    log_error "Usage: task attach <task-id> <file-path>"
    exit 1
  fi
  
  if [ ! -f "$file_path" ]; then
    log_error "File not found: $file_path"
    exit 1
  fi
  
  log_info "Attaching file to task $task_id..."
  
  # Get current task
  local response
  response=$(api_call GET "/tasks")
  
  local task
  task=$(echo "$response" | jq --arg id "$task_id" '.tasks | map(select(.id == $id)) | .[0]')
  
  if [ "$task" = "null" ]; then
    log_error "Task not found: $task_id"
    exit 1
  fi
  
  # Create attachment
  local filename
  filename=$(basename "$file_path")
  local mime_type
  case "${filename##*.}" in
    md|markdown) mime_type="text/markdown" ;;
    txt) mime_type="text/plain" ;;
    json) mime_type="application/json" ;;
    pdf) mime_type="application/pdf" ;;
    png) mime_type="image/png" ;;
    jpg|jpeg) mime_type="image/jpeg" ;;
    gif) mime_type="image/gif" ;;
    *) mime_type="application/octet-stream" ;;
  esac
  
  local base64_content
  base64_content=$(base64 -i "$file_path" | tr -d '\n')
  local data_url="data:$mime_type;base64,$base64_content"
  
  local attachment
  attachment=$(jq -n \
    --arg id "$(date +%s)" \
    --arg name "$filename" \
    --arg type "$mime_type" \
    --argjson size "$(stat -f%z "$file_path" 2>/dev/null || stat -c%s "$file_path")" \
    --arg dataUrl "$data_url" \
    --arg uploadedAt "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
    '{id: $id, name: $name, type: $type, size: $size, dataUrl: $dataUrl, uploadedAt: $uploadedAt}')
  
  local updated_task
  updated_task=$(echo "$task" | jq --argjson att "$attachment" '.attachments = (.attachments // []) + [$att]')
  
  api_call POST "/tasks" "{\"task\": $updated_task}"
}

#===================
# PROJECT OPERATIONS
#===================

cmd_project_list() {
  log_info "Fetching projects..."
  api_call GET "/projects" | jq '.projects'
}

cmd_project_get() {
  local project_id="$1"
  
  if [ -z "$project_id" ]; then
    log_error "Usage: project get <project-id>"
    exit 1
  fi
  
  log_info "Fetching project $project_id..."
  api_call GET "/projects/$project_id" | jq '.project'
}

cmd_project_create() {
  local name="$1"
  local description="${2:-}"
  local color="${3:-#3b82f6}"
  
  if [ -z "$name" ]; then
    log_error "Usage: project create <name> [description] [color]"
    exit 1
  fi
  
  log_info "Creating project: $name"
  local data
  data=$(jq -n --arg name "$name" --arg desc "$description" --arg color "$color" \
    '{name: $name, description: (if $desc == "" then null else $desc end), color: $color}')
  api_call POST "/projects" "$data"
}

cmd_project_update() {
  local project_id="$1"
  local field="$2"
  local value="$3"
  
  if [ -z "$project_id" ] || [ -z "$field" ]; then
    log_error "Usage: project update <id> <field> <value>"
    echo "Fields: name, description, color"
    exit 1
  fi
  
  log_info "Updating project $project_id: $field = $value"
  local data
  data=$(jq -n --arg id "$project_id" --arg field "$field" --arg value "$value" \
    '{id: $id, ($field): $value}')
  api_call PATCH "/projects" "$data"
}

cmd_project_delete() {
  local project_id="$1"
  
  if [ -z "$project_id" ]; then
    log_error "Usage: project delete <id>"
    exit 1
  fi
  
  log_warn "Deleting project $project_id..."
  api_call DELETE "/projects" "{\"id\": \"$project_id\"}"
}

#===================
# SPRINT OPERATIONS
#===================

cmd_sprint_list() {
  log_info "Fetching sprints..."
  api_call GET "/sprints" | jq '.sprints'
}

cmd_sprint_get() {
  local sprint_id="$1"
  
  if [ -z "$sprint_id" ]; then
    log_error "Usage: sprint get <sprint-id>"
    exit 1
  fi
  
  log_info "Fetching sprint $sprint_id..."
  api_call GET "/sprints/$sprint_id" | jq '.sprint'
}

cmd_sprint_create() {
  local name="$1"
  local project_id="$2"
  local start_date="${3:-}"
  local end_date="${4:-}"
  local goal="${5:-}"
  
  if [ -z "$name" ]; then
    log_error "Usage: sprint create <name> <project-id> [start-date] [end-date] [goal]"
    exit 1
  fi
  
  log_info "Creating sprint: $name"
  local data
  data=$(jq -n \
    --arg name "$name" \
    --arg projectId "$project_id" \
    --arg startDate "$start_date" \
    --arg endDate "$end_date" \
    --arg goal "$goal" \
    '{
      name: $name,
      projectId: $projectId,
      startDate: (if $startDate == "" then null else $startDate end),
      endDate: (if $endDate == "" then null else $endDate end),
      goal: (if $goal == "" then null else $goal end),
      status: "planning"
    }')
  api_call POST "/sprints" "$data"
}

cmd_sprint_update() {
  local sprint_id="$1"
  local field="$2"
  local value="$3"
  
  if [ -z "$sprint_id" ] || [ -z "$field" ]; then
    log_error "Usage: sprint update <id> <field> <value>"
    echo "Fields: name, goal, startDate, endDate, status, projectId"
    exit 1
  fi
  
  log_info "Updating sprint $sprint_id: $field = $value"
  local data
  data=$(jq -n --arg id "$sprint_id" --arg field "$field" --arg value "$value" \
    '{id: $id, ($field): $value}')
  api_call PATCH "/sprints" "$data"
}

cmd_sprint_delete() {
  local sprint_id="$1"
  
  if [ -z "$sprint_id" ]; then
    log_error "Usage: sprint delete <id>"
    exit 1
  fi
  
  log_warn "Deleting sprint $sprint_id..."
  api_call DELETE "/sprints" "{\"id\": \"$sprint_id\"}"
}

#===================
# AUTH OPERATIONS
#===================

cmd_auth_login() {
  local email="$1"
  local password="$2"
  
  if [ -z "$email" ] || [ -z "$password" ]; then
    log_error "Usage: auth login <email> <password>"
    exit 1
  fi
  
  log_info "Logging in..."
  api_call POST "/auth/login" "{\"email\": \"$email\", \"password\": \"$password\"}"
}

cmd_auth_logout() {
  log_info "Logging out..."
  api_call POST "/auth/logout" "{}"
}

cmd_auth_session() {
  log_info "Checking session..."
  api_call GET "/auth/session"
}

cmd_auth_register() {
  local email="$1"
  local password="$2"
  local name="${3:-}"
  
  if [ -z "$email" ] || [ -z "$password" ]; then
    log_error "Usage: auth register <email> <password> [name]"
    exit 1
  fi
  
  log_info "Registering user..."
  local data
  data=$(jq -n --arg email "$email" --arg password "$password" --arg name "$name" \
    '{email: $email, password: $password, name: (if $name == "" then null else $name end)}')
  api_call POST "/auth/register" "$data"
}

cmd_auth_forgot_password() {
  local email="$1"
  
  if [ -z "$email" ]; then
    log_error "Usage: auth forgot-password <email>"
    exit 1
  fi
  
  log_info "Requesting password reset..."
  api_call POST "/auth/forgot-password" "{\"email\": \"$email\"}"
}

cmd_auth_reset_password() {
  local token="$1"
  local password="$2"
  
  if [ -z "$token" ] || [ -z "$password" ]; then
    log_error "Usage: auth reset-password <token> <new-password>"
    exit 1
  fi
  
  log_info "Resetting password..."
  api_call POST "/auth/reset-password" "{\"token\": \"$token\", \"password\": \"$password\"}"
}

cmd_auth_account() {
  local field="$1"
  local value="$2"
  
  if [ -z "$field" ] || [ -z "$value" ]; then
    log_error "Usage: auth account <field> <value>"
    echo "Fields: name, email"
    exit 1
  fi
  
  log_info "Updating account $field..."
  local data
  data=$(jq -n --arg field "$field" --arg value "$value" '{($field): $value}')
  api_call PATCH "/auth/account" "$data"
}

cmd_auth_users() {
  log_info "Fetching users..."
  api_call GET "/auth/users"
}

#===================
# DEBUG OPERATIONS
#===================

cmd_debug() {
  log_info "Calling debug endpoint..."
  api_call GET "/debug"
}

#===================
# HELP
#===================

show_help() {
  cat << 'EOF'
Gantt Board CLI - Complete API Access

USAGE:
  ./gantt.sh <command> [subcommand] [args]

TASK COMMANDS:
  task list [status]              List all tasks (optionally filter by status)
  task get <id>                   Get specific task details
  task create <title> [status] [priority] [project-id]
                                  Create a new task
  task natural <text>             Create task from natural language
                                  Example: "Fix bug by Friday, high priority"
  task update <id> <field> <val>  Update task field
                                  Fields: status, priority, title, description,
                                          assigneeId, sprintId, dueDate
  task delete <id>                Delete a task
  task comment <id> <text>        Add a comment to a task
  task attach <id> <file>         Attach a file to a task

PROJECT COMMANDS:
  project list                    List all projects
  project get <id>                Get specific project
  project create <name> [desc] [color]
                                  Create new project
  project update <id> <field> <val>
                                  Update project field
                                  Fields: name, description, color
  project delete <id>             Delete a project

SPRINT COMMANDS:
  sprint list                     List all sprints
  sprint get <id>                 Get specific sprint
  sprint create <name> <project-id> [start] [end] [goal]
                                  Create new sprint
  sprint update <id> <field> <val>
                                  Update sprint field
                                  Fields: name, goal, startDate, endDate,
                                          status, projectId
  sprint delete <id>              Delete a sprint

AUTH COMMANDS:
  auth login <email> <pass>       Log in
  auth logout                     Log out
  auth session                    Check current session
  auth register <email> <pass>    Register new account
  auth forgot-password <email>    Request password reset
  auth reset-password <tok> <pass> Reset password with token
  auth account <field> <value>    Update account (name, email)
  auth users                      List all users

OTHER COMMANDS:
  debug                           Call debug endpoint
  help                            Show this help message

EXAMPLES:
  # List open tasks
  ./gantt.sh task list open

  # Create a task naturally
  ./gantt.sh task natural "Research TTS options by tomorrow, medium priority"

  # Update task status
  ./gantt.sh task update abc-123 status done

  # Add comment
  ./gantt.sh task comment abc-123 "Working on this now"

  # Attach file
  ./gantt.sh task attach abc-123 ./notes.md

ENVIRONMENT:
  API_URL    Override the API base URL (default: http://localhost:3000/api)

EOF
}

#===================
# MAIN
#===================

main() {
  check_deps
  
  local cmd="${1:-help}"
  shift || true
  
  case "$cmd" in
    task)
      local subcmd="${1:-list}"
      shift || true
      case "$subcmd" in
        list|ls) cmd_task_list "$@" ;;
        get|show) cmd_task_get "$@" ;;
        create|new|add) cmd_task_create "$@" ;;
        natural|parse) cmd_task_natural "$@" ;;
        update|set|edit) cmd_task_update "$@" ;;
        delete|rm|remove) cmd_task_delete "$@" ;;
        comment|note) cmd_task_comment "$@" ;;
        attach|file) cmd_task_attach "$@" ;;
        *) log_error "Unknown task command: $subcmd"; show_help; exit 1 ;;
      esac
      ;;
    project|projects)
      local subcmd="${1:-list}"
      shift || true
      case "$subcmd" in
        list|ls) cmd_project_list "$@" ;;
        get|show) cmd_project_get "$@" ;;
        create|new|add) cmd_project_create "$@" ;;
        update|set|edit) cmd_project_update "$@" ;;
        delete|rm|remove) cmd_project_delete "$@" ;;
        *) log_error "Unknown project command: $subcmd"; show_help; exit 1 ;;
      esac
      ;;
    sprint|sprints)
      local subcmd="${1:-list}"
      shift || true
      case "$subcmd" in
        list|ls) cmd_sprint_list "$@" ;;
        get|show) cmd_sprint_get "$@" ;;
        create|new|add) cmd_sprint_create "$@" ;;
        update|set|edit) cmd_sprint_update "$@" ;;
        delete|rm|remove) cmd_sprint_delete "$@" ;;
        *) log_error "Unknown sprint command: $subcmd"; show_help; exit 1 ;;
      esac
      ;;
    auth)
      local subcmd="${1:-session}"
      shift || true
      case "$subcmd" in
        login) cmd_auth_login "$@" ;;
        logout) cmd_auth_logout "$@" ;;
        session|whoami) cmd_auth_session "$@" ;;
        register|signup) cmd_auth_register "$@" ;;
        forgot-password|forgot) cmd_auth_forgot_password "$@" ;;
        reset-password|reset) cmd_auth_reset_password "$@" ;;
        account|profile) cmd_auth_account "$@" ;;
        users|list-users) cmd_auth_users "$@" ;;
        *) log_error "Unknown auth command: $subcmd"; show_help; exit 1 ;;
      esac
      ;;
    debug) cmd_debug "$@" ;;
    help|--help|-h) show_help ;;
    *) log_error "Unknown command: $cmd"; show_help; exit 1 ;;
  esac
}

main "$@"
