<?php

namespace Drupal\materio_migrate\Plugin\migrate\source;

use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;

/**
 * Drupal 7 Ubercart roles expiration source.
 *
 * This is for migrating roles granted with the uc_roles module to licenses.
 *
 * This class is just a starting point:
 * - The expiration settings are not handled. In particular, for licenses used
 *   with subscriptions, the expiry should be set to 'unlimited'.
 * - The case of more than one product selling the same role is not handled.
 * - Assumptions are made about renewals.
 *
 * @MigrateSource(
 *   id = "d7_uc_license_role",
 *   source_module = "uc_roles"
 * )
 */
class D7UcRolesLicense extends DrupalSqlBase {

  /**
   * {@inheritdoc}
   */
  public function query() {
    $query = $this->select('uc_roles_expirations', 'ure')
      ->fields('ure', [
        'reid',
        'uid',
        'rid',
        'expiration',
      ])
      // ->condition('ure.rid', 6)
      ->orderBy('ure.expiration');

    // // Joining to {uc_roles_products} gets us the product node ID and the
    // // duration configuration.
    // // TODO: this join assumes there is only one product per role. If some
    // // roles are sold by multiple products, this will break!
    // $query->innerJoin('uc_roles_products', 'urp', 'ure.rid = urp.rid');
    // $query->fields('urp', [
    //   'nid',
    //   'duration',
    //   'granularity',
    // ]);

    // // Get the orders that purchased this product.
    // // Join to {uc_orders} via {uc_order_products}, getting first the order
    // // line items that hold the product, and the the corresponding order.
    // $query->innerJoin('uc_order_products', 'uop', 'urp.nid = uop.nid');
    // // This join also ensures that the orders are purchased by the users who
    // // have a role granted.
    // $query->innerJoin('uc_orders', 'uo', 'uop.order_id = uo.order_id AND ure.uid = uo.uid');
    //
    // $query->fields('uop', ['order_product_id']);
    // $query->fields('uo', [
    //   'created',
    //   'modified',
    //   'order_id',
    // ]);

    // // Use a groupwise mininum selfjoin to get only the earliest order by each
    // // user for a role.
    // // TODO: this assumes that later orders are renewals, and that there are no
    // // gaps in a user's license ownership, e.g. user buys license, lets it
    // // expire, buys another one.
    // // TODO: this join should also have a condition on the product nid!
    // $query->leftJoin('uc_orders', 'uo_later', 'uo.uid = uo_later.uid AND uo.modified > uo_later.modified');
    // $query->isNull('uo_later.order_id');

    return $query;
  }

    /**
   * {@inheritdoc}
   */
  public function prepareRow(Row $row) {
    // drush_print("_ _ _ _ _");
    // drush_print('uid '. $row->getSourceProperty('uid'));
    // // Get the most recent order for this user and role product, if different
    // // from the earliest order we retrieved in query().
    // $query = $this->select('uc_order_products', 'uop');
    // $query->innerJoin('uc_orders', 'uo', 'uop.order_id = uo.order_id');
    // // $query->condition('uop.nid', $row->getSourceProperty('nid'));
    // $query->condition('uo.uid', $row->getSourceProperty('uid'));
    // // $query->condition('uo.order_id', $row->getSourceProperty('order_id'), '<>');
    // $query->fields('uo', [
    //   'order_id',
    //   'created',
    //   'modified',
    // ]);
    // $query->orderBy('created', DESC);
    // $query->range(0, 1);
    //
    // $latest_order_data = $query->execute()->fetchAssoc();
    // // print_r($latest_order_data);
    //
    // if ($latest_order_data) {
    //   // drush_print('renewed ' . $latest_order_data['created']);
    //   // Set the date of the last renewal to the creation date of the most
    //   // recent order for this role.
    //   // This is the closest thing we have?
    //   $row->setSourceProperty('renewed', $latest_order_data['created']);
    //   // drush_print('renewed ' . date('Y-m-d', $row->getSourceProperty('renewed')));
    // }
    // else {
    //   // drush_print('renewed NULL');
    //   $row->setSourceProperty('renewed', NULL);
    //   // drush_print('renewed NULL');
    // }

    $expiration = $row->getSourceProperty('expiration');
    $state = $expiration > time() ? 'active' : 'expired';
    $row->setSourceProperty('state', $state);

    // Get orders for this user
    // will get the first and the last if diffents.
    $query = $this->select('uc_order_products', 'uop');
    $query->innerJoin('uc_orders', 'uo', 'uop.order_id = uo.order_id');
    $query->condition('uo.uid', $row->getSourceProperty('uid'));
    $query->fields('uo', [
      'order_id',
      'created',
      'modified',
    ]);
    $query->orderBy('created', DESC);
    $orders = $query->execute()->fetchAll();
    // print_r($orders);

    // default renewed value
    $renewed = strtotime('-1 year', $expiration);
    $row->setSourceProperty('created', $renewed);
    $row->setSourceProperty('renewed', $renewed);

    // "real" created and renewed values
    if(count($orders)){
      $first_order = array_shift($orders);
      $row->setSourceProperty('created', $first_order['created']);
      $row->setSourceProperty('renewed', $first_order['created']);
      if(count($orders)){
        $last_order = array_pop($orders);
        $row->setSourceProperty('renewed', $last_order['created']);
      }
    }

    // $expirationstr = date('Y-m-d', $expiration);
    // drush_print('expiration ' . $expirationstr);

    return parent::prepareRow($row);
  }

  /**
   * {@inheritdoc}
   */
  public function fields() {
    return ([
      'reid' => $this->t('Record ID'),
      'uid' => $this->t('User ID'),
      'rid' => $this->t('The role ID'),
      'expiration' => $this->t('The expiration date'),
      'nid' => $this->t('Product node ID'),
      'duration' => $this->t('The interval multiplier'),
      'granularity' => $this->t('The interval'),
      'created' => $this->t('Earliest order created time'),
      'modified' => $this->t('Earliest order changed time'),
      'renewed' => $this->t('Latest order created time'),
    ]);
  }

  /**
   * {@inheritdoc}
   */
  public function getIds() {
    return [
      'reid' => [
        'type' => 'integer',
        'alias' => 'ure',
      ]
      // Add the order product ID as a key, so that order product migrations
      // can look up the license to reference it.
      // 'order_product_id' => [
      //   'type' => 'integer',
      // ],
    ];
  }

}
