#!/usr/bin/env ruby
# frozen_string_literal: true
#
# os-backlog CLI: board-ensure, activate, archive, resolve, card-add,
# cards, snapshot.
#
# Usage:
#   os-backlog board-ensure NAME --project Dev|Clients
#   os-backlog activate NAME
#   os-backlog archive NAME --yes
#   os-backlog resolve < input.json
#     input.json: {"repo_path": "...", "config": "..."|null, "boards": ["...", ...]}
#   os-backlog card-add --board NAME --title "..." [--description "..."]
#   os-backlog cards --board NAME              (human-readable per-list card listing)
#   os-backlog snapshot --board NAME           (full board state as JSON; read-only)
#
# board-ensure/activate/archive talk to Planka over the network (the
# installed planka-api gem, credentials from PLANKA_BASE_URL/USERNAME/
# PASSWORD). resolve is pure — no network access at all.
#
# Fails soft: if the gem or Planka credentials are unavailable, prints one
# clear error and exits nonzero. Never destructive.

require "json"
require_relative "../lib/backlog"

def fail_soft(message)
  warn "os-backlog: #{message}"
  exit 1
end

def build_client
  require "planka_api"
  client = Planka::Client.new
  client.login
  client
rescue LoadError
  fail_soft("the planka-api gem is not installed/loadable; cannot reach Planka")
rescue StandardError => e
  fail_soft("could not authenticate to Planka: #{e.message}")
end

def parse_project_flag(args)
  idx = args.index("--project")
  return "Dev" unless idx

  args.delete_at(idx)
  project = args.delete_at(idx)
  project || fail_soft("--project requires a value (Dev or Clients)")
end

def parse_flag(args, flag)
  idx = args.index(flag)
  return nil unless idx

  args.delete_at(idx)
  args.delete_at(idx)
end

def require_flag(args, flag, command)
  parse_flag(args, flag) || fail_soft("#{command} requires #{flag} <value>")
end

command, *rest = ARGV

begin
case command
when "board-ensure"
  name = rest.shift
  fail_soft("board-ensure requires a board name") unless name
  project = parse_project_flag(rest)
  client = build_client
  result = Backlog::BoardEnsurer.new(client: client).ensure(name, project_name: project)
  puts "board #{result.board['name']} (#{result.created ? 'created' : 'existing'}) " \
       "in project #{project}; lists created: #{result.lists_created.join(', ')}; " \
       "labels created: #{result.labels_created.join(', ')}"
when "activate"
  name = rest.shift
  fail_soft("activate requires a board name") unless name
  client = build_client
  board = Backlog::BoardEnsurer.new(client: client).activate(name)
  puts "activated: #{board['name']}"
when "archive"
  name = rest.shift
  fail_soft("archive requires a board name") unless name
  fail_soft("archive requires explicit --yes (human go-ahead only)") unless rest.include?("--yes")

  client = build_client
  board = Backlog::BoardEnsurer.new(client: client).archive(name)
  puts "archived: #{board['name']}"
when "resolve"
  input = JSON.parse($stdin.read)
  resolver = Backlog::Resolver.new(
    repo_path: input.fetch("repo_path"),
    config_contents: input["config"],
    boards: input.fetch("boards", [])
  )
  puts resolver.resolve_string
when "card-add"
  board = require_flag(rest, "--board", "card-add")
  title = require_flag(rest, "--title", "card-add")
  description = parse_flag(rest, "--description")
  client = build_client
  card = Backlog::Cards.new(client: client).add(board_name: board, title: title, description: description)
  puts "created card ##{card['id']} at Backlog on #{board}: #{card['name']}"
when "cards"
  board = require_flag(rest, "--board", "cards")
  client = build_client
  snapshot = Backlog::Cards.new(client: client).snapshot(board_name: board)
  snapshot["lists"].each do |list|
    puts "#{list['name']} (#{list['cards'].size})"
    list["cards"].each do |card|
      labels = card["labels"].empty? ? "" : " [#{card['labels'].join(', ')}]"
      puts "  - #{card['name']}#{labels}"
    end
  end
when "snapshot"
  board = require_flag(rest, "--board", "snapshot")
  client = build_client
  puts JSON.pretty_generate(Backlog::Cards.new(client: client).snapshot(board_name: board))
when nil, "-h", "--help"
  puts <<~USAGE
    usage: os-backlog <command> [options]

    commands:
      board-ensure NAME --project Dev|Clients
      activate NAME
      archive NAME --yes
      resolve   (reads {"repo_path","config","boards"} JSON from stdin)
      card-add --board NAME --title "..." [--description "..."]
      cards --board NAME
      snapshot --board NAME
  USAGE
  exit(command.nil? ? 1 : 0)
else
  fail_soft("unknown command #{command.inspect}")
end
rescue SystemExit
  raise
rescue StandardError => e
  fail_soft(e.message)
end
