<?php

require_once '/usr/local/src/phabricator/scripts/__init_script__.php';

$args = new PhutilArgumentParser($argv);
$args->parseStandardArguments();
$args->parse([
  [
    'name'  => 'user',
    'param' => 'username',
    'help'  => pht(
      'The acting user. Transactions will be generated on '.
      'behalf of this user.'),
  ],
  [
    'name'  => 'project',
    'param' => 'slug',
    'help'  => pht('The project slug.'),
  ],
  [
    'name'  => 'column',
    'param' => 'name',
    'help'  => pht(
      'The destination column. All matching tasks will be moved to '.
      'this column on the project workboard.'),
  ],
  [
    'name'  => 'dry-run',
    'help'  => pht(
      'If this flag is specified, the script will not perform any '.
      'writes but rather will output the intended operations to the '.
      'console for verification.'),
  ],
  [
    'name'     => 'tasks',
    'wildcard' => true,
  ],
]);

$username = $args->getArg('user');
if (!$username) {
  echo pht('You must specify an acting user.')."\n";
  exit(1);
}

$viewer = (new PhabricatorPeopleQuery())
  ->setViewer(PhabricatorUser::getOmnipotentUser())
  ->withUsernames([$args->getArg('user')])
  ->executeOne();
if (!$viewer) {
  throw new Exception(pht("User '%s' not found!", $username));
}

$project_slug = $args->getArg('project');
if (!$project_slug) {
  echo pht('You must specify a project.')."\n";
  exit(1);
}
$project = (new PhabricatorProjectQuery())
  ->setViewer($viewer)
  ->withSlugs([$project_slug])
  ->executeOne();
if (!$project) {
  throw new Exception(pht("Project '#%s' not found!", $project_slug));
}

$column_name = $args->getArg('column');
if (!$column_name) {
  echo pht('You must specify a column.')."\n";
  exit(1);
}
$column = (new PhabricatorProjectColumn())->loadOneWhere(
  'projectPHID = %s AND name = %s', 
  $project->getPHID(), 
  $column_name);
if (!$column) {
  throw new Exception(pht("Column '%s' not found!", $column_name));
}

$tasks = id(new ManiphestTaskQuery())
  ->setViewer($viewer)
  ->withIDs($args->getArg('tasks'))
  ->execute();

$console = PhutilConsole::getConsole();
$editor = (new ManiphestTransactionEditor())
  ->setActor($viewer)
  ->setContentSource(PhabricatorContentSource::newForSource(PhabricatorUnknownContentSource::SOURCECONST));

foreach ($tasks as $task) {
  $position = (new PhabricatorProjectColumnPositionQuery())
    ->setViewer($viewer)
    ->withBoardPHIDs([$column->getProjectPHID()])
    ->withObjectPHIDs([$task->getPHID()])
    ->executeOne();
  
  if (!$position) {
    throw new Exception(
      pht('Position not found for task %s!', $task->getPHID()));
  }

  if ($position->getColumnPHID() === $column->getPHID()) {
    $console->writeOut(
      pht(
        "Task %s (%s) does not need to be moved.\n",
        $task->getPHID(),
        $task->getMonogram()));
    continue;
  }

  if ($args->getArg('dry-run')) {
    $console->writeOut(
      pht(
        "Task %s (%s) would be moved from %s to %s.\n",
        $task->getPHID(),
        $task->getMonogram(),
        $position->getColumnPHID(),
        $column->getPHID()));
    continue;
  }

  $xactions = [];
  $xactions[] = (new ManiphestTransaction())
    ->setTransactionType(PhabricatorTransactions::TYPE_COLUMNS)
    ->setNewValue([
      'columnPHID' => $column->getPHID(),
    ]);

  $editor->applyTransactions($task, $xactions);
  $console->writeOut(
    pht(
      "Task %s (%s) moved from %s to %s.\n",
      $task->getPHID(),
      $task->getMonogram(),
      $position->getColumnPHID(),
      $column->getPHID()));
}

$console->writeOut(pht('Done!')."\n");