<?php

/**
 * @file
 * A drush script that imports/updates migrated pages.
 */

use Drupal\node\Entity\Node;

// This is the csv file holdings the list of incoming legacy URLs.
// @see README.md
$source_urls_csv = dirname(__FILE__) . '/../source_urls.csv';

if (file_exists($source_urls_csv)) {
  // Log all the errors together.
  $error_log = [];

  $file_lines = file($source_urls_csv);
  // Get rid of the CSV header.
  array_shift($file_lines);

  // Array to hold already located term names.
  $navigation_terms = [];

  // Iterate through all the lines and extract the URL and title.
  foreach ($file_lines as $index => $file_line) {
    $line_tokens = array_map(
      function ($value) {
        return trim($value);
      },
      array_filter(
        explode("\t", $file_line),
        function ($value) {
          return !empty(trim($value));
        }
      )
    );

    $title = trim(array_shift($line_tokens));
    $url = trim(array_shift($line_tokens));

    $nids = \Drupal::entityQuery('node')
      ->condition('type', 'page')
      ->condition('field_migration_source_url', $url)
      ->execute();

    $navigation_term_key = implode('>>', $line_tokens);
    print "$navigation_term_key\n";
    $term_name = array_pop($line_tokens);

    // Some memoization in order here.
    if (isset($navigation_terms[$navigation_term_key])) {
      $term_tid = $navigation_terms[$navigation_term_key];
    }
    else {
      $term = locate_term($term_name, $line_tokens);
      if ($term) {
        $term_tid = $navigation_terms[$navigation_term_key] = $term->id();
      }
      // The term was not found, should be logged somewhere.
      else {
        $term_tid = 0;
      }
    }

    // Create.
    if (empty($nids)) {
      $node_values = [
        'type' => 'page',
        'title' => $title,
        'field_migration_source_url' => $url,
        'status' => 0,
        'uid' => 1,
      ];
      if ($term_tid > 0 && $term) {
        $node_values['field_navigation'] = $term->id();
      }
      $node = Node::create($node_values);
      $node->save();
    }
    // Update.
    else {
      $nid = array_shift($nids);
      $node = Node::load($nid);
      $node->title = $title;
      if ($term_tid > 0 && $term) {
        $node->field_navigation = $term;
      }
      $node->save();
    }
    // Logging problematic Navigation paths to STDERR.
    if ($term_tid == 0) {
      $error_log[] = t(
        '[line @line] @url have a wrong navigation path [@navigation_term_key]',
        [
          '@url' => $url,
          '@line' => $index,
          '@navigation_term_key' => $navigation_term_key,
        ]
      );
    }
  }

  // Report all the errors in one single log message.
  if ($error_log) {
    fwrite(STDERR, implode("\n", $error_log));
    \Drupal::logger('SVV legacy content import')->notice(implode("<br>\n", $error_log));
  }
}

/**
 * Finds a term given its name  and parents, in the 'navigation' vocabulary.
 */
function locate_term($term_name, $parents_names) {
  if (isset($term_name)) {
    $terms = get_terms_by_name($term_name, 'navigation');

    foreach ($terms as $tid => $term) {
      $parents = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadAllParents($tid);
      array_shift($parents);

      // We need at least one parent in the hierarchy to identify the term
      // No need to check all of them, because the hierarchy and levels can change.
      if ($parents_names) {
        $term_parents_found = [];
        foreach ($parents as $parent) {
          if (in_array($parent->label(), $parents_names)) {
            $term_parents_found[] = $parent->label();
          }
        }

        // If neither one parent has been found return false.
        if (!count($term_parents_found)) {
          return NULL;
        }
      }

      if ($term) {
        return $term;
      }
    }
  }
  return NULL;
}

/**
 * Finds a term given its name  and parents, in the 'navigation' vocabulary.
 */
function get_terms_by_name($name = NULL, $vid = NULL) {
  $properties = [];
  if (!empty($name)) {
    $properties['name'] = $name;
  }
  if (!empty($vid)) {
    $properties['vid'] = $vid;
  }
  $terms = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadByProperties($properties);
  return $terms;
}
