<?php

namespace Drupal\autoslave\Controller;

use Drupal\Core\Database\Driver\autoslave\Install\Tasks;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Database\Database;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Controller routines for autoslave routes.
 */
class AutoslaveController extends ControllerBase {

  /**
   * The module handler.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected $moduleHandler;

  /**
   * Constructs an AutoslaveController object.
   *
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   *   The module handler.
   */
  public function __construct(ModuleHandlerInterface $module_handler) {
    $this->moduleHandler = $module_handler;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('module_handler')
    );
  }

  /**
   * AutoSlave Status Page.
   */
  public function autoslaveStatus() {

    if (!autoslave_is_driver_loaded()) {
      \Drupal::messenger()->addMessage(t('AutoSlave driver is not loaded'), 'warning');
      return [
        '#markup' => '',
      ];
    }

    // Load .install files - use proper Drupal 10 method.
    $this->moduleHandler->loadInclude('autoslave', 'install');

    // Create install task instance if available.
    if (class_exists('\Drupal\Core\Database\Driver\autoslave\Install\Tasks')) {
      $tasks = new Tasks();
    }
    else {
      // Fallback if Tasks class not found.
      $tasks = NULL;
    }

    $databases = Database::getAllConnectionInfo();
    foreach ($databases as $key => $targets) {
      foreach ($targets as $target => $conninfo) {
        $conninfos = empty($conninfo['driver']) ? $conninfo : [$conninfo];
        foreach ($conninfos as $conninfo) {
          if ($conninfo['driver'] != 'autoslave') {
            continue;
          }
          if ($tasks && method_exists($tasks, 'connectionStatusTable')) {
            $build = $tasks->connectionStatusTable(Database::getConnection($target, $key));
          }
          else {
            $build = ['#markup' => '<p>' . $this->t('AutoSlave status information not available.') . '</p>'];
          }
        }
      }
    }

    return $build;
  }

  /**
   * AutoSlave Affected Tables Page.
   */
  public function affectedTables() {
    if (!autoslave_is_driver_loaded()) {
      \Drupal::messenger()->addMessage(t('AutoSlave driver is not loaded'), 'warning');
    }

    $active = [];
    $inactive = [];
    $databases = Database::getAllConnectionInfo();
    foreach ($databases as $key => $targets) {
      foreach ($targets as $target => $conninfos) {
        if (isset($conninfos['driver'])) {
          $conninfos = [$conninfos];
        }
        foreach ($conninfos as $conninfo) {
          if ($conninfo['driver'] !== 'autoslave' || (isset($conninfo['global replication lag']) && !$conninfo['global replication lag'])) {
            continue;
          }
          try {
            $tables = Database::getConnection($target, $key)->getAffectedTables(time());
            foreach ($tables as $row) {
              $timestamp_expiry = $row['expires'];
              $desc = t('expires in @expires_in seconds', ['@expires_in' => $row['expires'] - time()]);
              $row['expires'] = date('Y-m-d H:i:s', $row['expires']) . " ($desc)";

              $desc = t('invalidated @age seconds ago', ['@age' => time() - $row['invalidated']]);
              $row['invalidated'] = date('Y-m-d H:i:s', $row['invalidated']) . " ($desc)";
              if ($timestamp_expiry > $_SERVER['REQUEST_TIME']) {
                $active[$row['db_key'] . ':' . $row['db_target'] . ':' . $row['affected_table']] = [
                  'key' => $row['db_key'],
                  'target' => $row['db_target'],
                  'table' => $row['affected_table'],
                  'invalidated' => $row['invalidated'],
                  'expires' => $row['expires'],
                  'in_sync' => isset($row['wcnt1_slave']) ? ($row['wcnt1_slave'] === $row['wcnt1'] ? t('Yes') : t('No')) : t('N/A'),
                ];
              }
              else {
                $inactive[$row['db_key'] . ':' . $row['db_target'] . ':' . $row['affected_table']] = [
                  'key' => $row['db_key'],
                  'target' => $row['db_target'],
                  'table' => $row['affected_table'],
                  'invalidated' => $row['invalidated'],
                  'expires' => $row['expires'],
                  'in_sync' => isset($row['wcnt1_slave']) ? ($row['wcnt1_slave'] === $row['wcnt1'] ? t('Yes') : t('No')) : t('N/A'),
                ];
              }

            }

          }
          catch (\Exception $e) {
            \Drupal::messenger()->addMessage(t('Error connecting to: [@key][@target]', [
              '@key' => $conninfo['key'],
              '@target' => $conninfo['target'],
            ]), 'error');
          }
        }
      }
    }
    $header = [t('Key'), t('Target'), t('Table'), t('Invalidated'), t('Expires'), t('In sync.')];

    $build = [];
    $build['active-tables-title'] = [
      '#type' => 'markup',
      '#markup' => '<h2>' . t('Active!') . '</h2>',
    ];
    $build['active-tables'] = [
      '#type' => 'table',
      '#header' => $header,
      '#rows' => $active,
    ];
    $build['inactive-tables-title'] = [
      '#type' => 'markup',
      '#markup' => '<h2>' . t('Inactive') . '</h2>',
    ];
    $build['inactive-tables'] = [
      '#type' => 'table',
      '#header' => $header,
      '#rows' => $inactive,
    ];

    return $build;
  }

}
