<?php

namespace Drupal\ufc\Commands;

use Drupal\ufc\Services\FighterImporter;
use Drupal\ufc\Services\FightImporter;
use Drupal\Core\Batch\BatchBuilder;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\node\Entity\Node;
use Drush\Commands\DrushCommands;
use Drush\Attributes as CLI;
use Symfony\Component\DomCrawler\Crawler;

class UfcCommands extends DrushCommands {

  /**
   * The UFC fighter list cache ID.
   */
  protected $cacheId = 'ufc:fighter-list';

  /**
   * Import fighters from UFC.com JSON:API.
   */
  #[CLI\Command(name: 'ufc:import-fighters', aliases: ['impft'])]
  public function importFighters(): void {
    // Fighter importer service.
    $fighter_importer = \Drupal::service('ufc.import_fighters');
    // First check for the item in cache.
    $fighter_list = \Drupal::cache()->get($this->cacheId);
    if (!$fighter_list) {
      dump("Getting fighters from UFC.com JSON:API");
      $fighter_list = $fighter_importer->getListOfCurrentFighters();
      \Drupal::cache()->set($this->cacheId, $fighter_list, CacheBackendInterface::CACHE_PERMANENT);
    }
    else {
      $fighter_list = $fighter_list->data;
    }

    $fighter_import_queue = \Drupal::queue('fighter_import');
    foreach ($fighter_list as $fighter) {
      $queue_item = new \stdClass();
      $queue_item->id = $fighter['id'];
      $fighter_import_queue->createItem($queue_item);
    }
  }

  /**
   * Import events based on ESPN.com.
   */
  #[CLI\Command(name: 'ufc:import-events', aliases: ['impev'])]
  public function importEvents(): void {
    $fight_importer = \Drupal::service("ufc.import_fights");
    $event_list = [];
    $events_base= "https://www.espn.com/mma/schedule/_/year/";
    $event_base = "https://www.espn.com";

    // Old fashioned for loop to target years.
    for ($i = 2000; $i <= 2025; $i++) {
      $year_event_url = $events_base . "{$i}/league/ufc";
      $event_listing = \Drupal::httpClient()
        ->get($year_event_url)->getBody()->getContents();
      $crawler = new Crawler($event_listing);
      $events = $crawler->filter('.Schedule__EventLeague--ufc tbody tr');
      foreach ($events as $event) {
        $event_list[$i][] = $event;
      }
    }

    // Add each division to a batch process.
    $batch = new BatchBuilder();
    $batch->setTitle("Starting Event Import")
      ->setFinishCallback([UfcCommands::class, 'eventImportFinished'])
      ->setInitMessage("Importing events...");
    foreach ($event_list as $year => $events) {
      foreach ($events as $event) {
        $args = [
          $event,
          $year,
        ];
        $batch->addOperation([FightImporter::class, 'processEvent'], $args);
      }
    }

    // Set and run the batch.
    batch_set($batch->toArray());
    drush_backend_batch_process();
  }

  /**
   * Update fights with their event date.
   */
  #[CLI\Command(name: 'ufc:update-fight-dates', aliases: ['ufd'])]
  public function updateFightDates(): void {
    // Get all fights
    $fights = \Drupal::entityTypeManager()->getStorage('node')->loadByProperties(['type' => 'fight']);
    // Add each division to a batch process.
    $batch = new BatchBuilder();
    $batch->setTitle("Starting Fight Update")
      ->setFinishCallback([UfcCommands::class, 'eventImportFinished'])
      ->setInitMessage("Importing events...");
    foreach ($fights as $fight) {
      $args = [
        $fight,
      ];
      $batch->addOperation([UfcCommands::class, 'updateFight'], $args);
    }
    // Set and run the batch.
    batch_set($batch->toArray());
    drush_backend_batch_process();
  }

  public static function updateFight($fight, $context) {
    $fight->field_fight_date = [UfcCommands::class, 'getEventDateTimestampFromFight', $fight];
    if ($fight->save()) {
      \Drupal::messenger()->addMessage($fight->title->value . " updated successfully.");
    }
    else {
      \Drupal::messenger()->addMessage($fight->title->value . " failed.");
    }
  }

  /**
   * Create Fights.
   */
  #[CLI\Command(name: 'ufc:create-fights', aliases: ['cf'])]
  public function createUfcFights(): void {
    $existing_fights = \Drupal::entityTypeManager()->getStorage('node')->loadByProperties(['type' => 'fight']);
    foreach ($existing_fights as $existing_fight) {
      $delete = $existing_fight->delete();
      if ($delete) {
        \Drupal::logger('ufc')->notice("Removed " . $existing_fight->getTitle());
      }
    }
    // Get all events - add each to queue, fights created per event.
    $events = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadByProperties(['vid' => 'ufc_events']);
    // Add each division to a batch process.
    $batch = new BatchBuilder();
    $batch->setTitle("Creating fights in batches....")
      ->setFinishCallback([UfcCommands::class, 'importFinished'])
      ->setInitMessage("Processing");
    foreach ($events as $event) {
      if ($event->field_event_url->uri == '/mma/fightcenter/_/id/600037492/league/ufc') {
        continue;
      }
      $args = [
        $event,
      ];
      $batch->addOperation([FightImporter::class, 'createFightsByEvent'], $args);
    }
    // Set and run the batch.
    batch_set($batch->toArray());
    drush_backend_batch_process();
  }

  /**
   * Gets the event date as a timestamp.
   */
  private function getEventDateTimestampFromFight(Node $fight_node): int|bool {
    // Get field value.
    $event_date_value = $fight_node->field_event->entity->field_event_date->value;
    assert($event_date_value, !null);

    return strtotime($event_date_value);
  }

  /**
   * Handle batch completion.
   *
   * @param bool $success
   *   TRUE if all batch API tasks were completed successfully.
   * @param array $results
   *   An results array from the batch processing operations.
   * @param array $operations
   *   A list of the operations that had not been completed.
   * @param string $elapsed
   *   Batch.inc kindly provides the elapsed processing time in seconds.
   */
  public static function importFinished(bool $success, array $results, array $operations, string $elapsed): void {
    // Finish the batch here.
    $message = "Processed " . $results['processed'] . " divisions.";
    \Drupal::messenger()->addMessage($message);
  }

  /**
   * Handle batch completion.
   *
   * @param bool $success
   *   TRUE if all batch API tasks were completed successfully.
   * @param array $results
   *   An results array from the batch processing operations.
   * @param array $operations
   *   A list of the operations that had not been completed.
   * @param string $elapsed
   *   Batch.inc kindly provides the elapsed processing time in seconds.
   */
  public static function eventImportFinished(bool $success, array $results, array $operations, string $elapsed): void {
    // Finish the batch here.
    $message = "Processed " . $results['processed'] . " events.";
    \Drupal::messenger()->addMessage($message);
  }

}
