#!/usr/bin/env ruby
# frozen_string_literal: true

# YATFA Agent Runner (Yet Another Tool For Agents)
# Usage: npx yatfa [worker|planner|reviewer|researcher]
#        npx yatfa setup
#        npx yatfa ps [--json]
#
# Requirements:
#   - Docker
#   - Ruby
#   - Dockerfile.sandbox in project root
#   - yatfa.env.rb in project root (gitignored)

require_relative "../lib/yatfa_agent/config"
require_relative "../lib/yatfa_agent/docker"
require_relative "../lib/yatfa_agent/http"
require_relative "../lib/yatfa_agent/agent"
require_relative "../lib/yatfa_agent/setup"
require_relative "../lib/yatfa_agent/updater"
require_relative "../lib/yatfa_agent/installer"
require_relative "../lib/yatfa_agent/ps"
require_relative "../agents"

def current_version
  require "json"
  real_path = File.realpath(__FILE__)
  package_json_path = File.join(File.dirname(real_path), "..", "package.json")
  JSON.parse(File.read(package_json_path))["version"]
end

def latest_npm_version
  data = YatfaAgent::HTTP.get("https://registry.npmjs.org/yatfa/latest")
  data&.dig("version")
rescue StandardError
  nil
end

def check_version!
  local = current_version
  remote = latest_npm_version
  return if remote.nil? || local == remote

  # Guard against infinite re-exec loop
  if ENV["YATFA_SELF_UPDATE"] == "1"
    puts "⚠️  Still outdated after self-update: v#{local} (latest: v#{remote})"
    puts "   Run manually: npx yatfa@latest #{ARGV.join(' ')}"
    return # continue anyway rather than blocking
  end

  puts "🔄 Auto-updating yatfa: v#{local} → v#{remote}..."

  # Clean up ALL stale installs so npx fetches fresh from registry
  begin
    real_path = File.realpath(__FILE__)
    install_dir = File.expand_path("../..", real_path) # bin/../.. → package root
    FileUtils.rm_rf(install_dir) if install_dir.include?("node_modules/yatfa")

    # Also clear npx cache (~/.npm/_npx/<hash>/node_modules/yatfa)
    npx_cache = File.join(Dir.home, ".npm", "_npx")
    if Dir.exist?(npx_cache)
      Dir.glob(File.join(npx_cache, "*", "node_modules", "yatfa")).each do |cached|
        FileUtils.rm_rf(cached)
      end
    end
  rescue StandardError
    # Best-effort cleanup — fall through to re-exec regardless
  end

  # Re-exec with @latest to force a fresh fetch from the registry
  ENV["YATFA_SELF_UPDATE"] = "1"
  exec("npx", "yatfa@latest", *ARGV)
rescue StandardError => e
  puts "⚠️  Auto-update failed: #{e.message}"
  puts "   Run manually: npx yatfa@latest #{ARGV.join(' ')}"
  exit 1
end

def show_version
  puts "yatfa v#{current_version}"
  exit 0
end

def show_usage
  puts "YATFA Agent Runner (Yet Another Tool For Agents)"
  puts ""
  puts "Usage:"
  puts "  npx yatfa version                             # Show version"
  puts "  npx yatfa setup                               # Interactive setup wizard"
  puts "  npx yatfa [worker|planner|reviewer|researcher] # Run agent (prompts to attach)"
  puts "  npx yatfa ps [--json]                         # List local agents + server status"
  puts "  npx yatfa update-agents [--once]              # Update stale agent containers"
  puts "  npx yatfa install-updater [--uninstall]       # Install/remove auto-update service"
  puts ""
  puts "Options:"
  puts "  --no-prompt, -d    Run without prompts (for CI/scripts)"
  puts "  YATFA_NO_PROMPT=1  Environment variable alternative"
  puts ""
  puts "Setup:"
  puts "  Run 'npx yatfa setup' for interactive configuration"
  puts ""
  puts "Manual setup:"
  puts "  1. Create Dockerfile.sandbox (see https://github.com/RoM4iK/yatfa-public/blob/main/README.md)"
  puts "  2. Create yatfa.env.rb (see https://github.com/RoM4iK/yatfa-public/blob/main/README.md)"
  puts "  3. echo 'yatfa.env.rb' >> .gitignore"
  puts "  4. npx yatfa worker"
  exit 1
end

# Main
show_usage if ARGV.empty?

command = ARGV[0].downcase

# Handle version command (skip version check — user is just asking what version they have)
show_version if %w[version -v --version].include?(command)

# Check for updates before doing anything else
check_version!

# Handle setup command
if command == "setup"
  wizard = YatfaAgent::Setup::SetupWizard.new
  wizard.run
  exit 0
end

# Handle update-agents command (runs on host, no project config needed)
if command == "update-agents"
  once = ARGV.include?("--once")
  interval = ENV.fetch("YATFA_UPDATE_INTERVAL", (4 * 60 * 60).to_s).to_i
  YatfaAgent::Updater.run(once: once, interval: interval)
  exit 0
end

# Handle install-updater command (runs on host, no project config needed)
if command == "install-updater"
  uninstall = ARGV.include?("--uninstall")
  YatfaAgent::Installer.run(uninstall: uninstall)
  exit 0
end

# Resolve project root by walking up the directory tree.
# This allows running `npx yatfa` from subfolders inside the project.
# Skipped for setup (which creates new config in cwd).
project_root = YatfaAgent::Config.find_project_root
if project_root && project_root != Dir.pwd
  puts "📂 Running from subfolder, using config from #{project_root}"
  Dir.chdir(project_root)
end

# Handle ps command — list local agent containers with server-side status.
# Needs project config (for the API key) but not repository fetching.
if command == "ps"
  config = YatfaAgent::Config.load(allow_remote_fetch: true)
  YatfaAgent::Ps.run(ARGV, config, AGENT_CONFIGS)
  exit 0
end

# Handle attach command (deprecated - will still work)
if command == "attach"
  puts ""
  puts "⚠️  Deprecation: The 'attach' command is deprecated"
  puts "   Running `npx yatfa <agent-type>` now prompts to attach automatically."
  puts ""
  agent_type = ARGV[1]&.downcase
  abort "Usage: npx yatfa attach [agent-type]" unless agent_type
  config = YatfaAgent::Config.load(allow_remote_fetch: true)
  YatfaAgent::Config.fetch_repositories!(config)
  YatfaAgent::Agent.attach(agent_type, config, AGENT_CONFIGS)
else
  # Handle run commands (worker, planner, reviewer, researcher)
  config = YatfaAgent::Config.load(allow_remote_fetch: true)
  # Fetch repositories from Rails API before building
  YatfaAgent::Config.fetch_repositories!(config)
  # Note: Docker.build_image is called inside Agent.run() only when a new
  # container actually needs to be created (not for attach/start-existing)
  # For "run" command, use second argument as agent type
  # For "attach" command, handled separately above
  agent_type_to_run = (command == "run") ? ARGV[1] : command
  YatfaAgent::Agent.run(agent_type_to_run, config, AGENT_CONFIGS)
end
