<?php

declare(strict_types=1);

namespace Drupal\acquia_dam\Form;

use Drupal\acquia_dam\AssetUpdater;
use Drupal\acquia_dam\Service\IntegrationLinksBatchProcessor;
use Drupal\acquia_dam\Service\IntegrationLinksQueueService;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Configuration form for Acquia DAM Integration Links.
 */
class AcquiaDamIntegrationLinksForm extends FormBase {

  /**
   * Constructs a new AcquiaDamIntegrationLinksForm.
   *
   * @param \Drupal\acquia_dam\Service\IntegrationLinksQueueService $queueService
   *   The integration links queue service.
   * @param \Drupal\acquia_dam\Service\IntegrationLinksBatchProcessor $batchProcessor
   *   The integration links batch processor service.
   * @param \Drupal\acquia_dam\AssetUpdater $assetUpdater
   *   The asset updater service.
   */
  public function __construct(
    protected IntegrationLinksQueueService $queueService,
    protected IntegrationLinksBatchProcessor $batchProcessor,
    protected AssetUpdater $assetUpdater,
    protected EntityTypeManagerInterface $entityTypeManager,
    protected Connection $database,
  ) {}

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container): static {
    return new static(
      $container->get('acquia_dam.integration_links_queue_service'),
      $container->get('acquia_dam.integration_links_batch_processor'),
      $container->get('acquia_dam.asset_updater'),
      $container->get('entity_type.manager'),
      $container->get('database'),
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId(): string {
    return 'acquia_dam_integration_links_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state): array {
    $form['#tree'] = TRUE;

    $form['description'] = [
      '#markup' => '<p>' . $this->t('Integration links help track where DAM assets are used in your Drupal site. Register links to see usage information in Acquia DAM.') . '</p>',
    ];

    // Get current statistics.
    $queue_count = $this->queueService->getQueueCount();
    $dam_media_types = $this->assetUpdater->getDamMediaTypes();
    $is_enhanced_mode = $this->batchProcessor->isEnhancedModeEnabled();

    // Calculate total DAM assets and registered integration links count.
    $total_assets = $total_registered = 0;
    $media_type_stats = [];
    foreach ($dam_media_types as $media_type_id) {
      $storage = $this->entityTypeManager->getStorage('media');

      // Get total count for this media type.
      $count = (int) $storage->getQuery()
        ->condition('bundle', $media_type_id)
        ->accessCheck(FALSE)
        ->count()
        ->execute();

      // Count how many already have registered integration links.
      // Query media entities of this type that have entries in tracking table.
      $registered_count = (int) $this->database->select('media', 'm')
        ->fields('m', ['mid'])
        ->condition('m.bundle', $media_type_id)
        ->condition('m.uuid', '', '!=')
        ->exists($this->database->select('acquia_dam_integration_link_tracking', 't')
          ->fields('t', ['entity_uuid'])
          ->where('t.entity_uuid = m.uuid')
        )
        ->countQuery()
        ->execute()
        ->fetchField();

      $remaining = $count - $registered_count;

      $total_assets += $count;
      $total_registered += $registered_count;

      // Load media type entity to get its label.
      $media_type = $this->entityTypeManager->getStorage('media_type')->load($media_type_id);
      $media_type_stats[$media_type_id] = [
        'label' => $media_type ? $media_type->label() : $media_type_id,
        'total' => $count,
        'registered' => $registered_count,
        'remaining' => $remaining,
      ];
    }

    // Status section.
    $form['status'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Current Status'),
    ];

    $header = [
      $this->t('Type'),
      $this->t('Total'),
      $this->t('Registered'),
      $this->t('Remaining'),
      $this->t('Status'),
    ];

    $rows = [];

    // Overall totals row.
    $total_remaining = $total_assets - $total_registered;
    $overall_status = ($total_assets <= 0)
      ? $this->t('N/A')
      : ($total_remaining > 0 ? $this->t('In progress') : $this->t('All registered ✓'));
    $rows[] = [
      'data' => [
        ['data' => $this->t('All DAM assets')],
        ['data' => $total_assets],
        ['data' => $total_registered],
        ['data' => $total_assets - $total_registered],
        ['data' => $overall_status],
      ],
    ];

    if (!empty($media_type_stats)) {
      foreach ($media_type_stats as $media_type_id => $stats) {
        $status = ($stats['total'] <= 0)
          ? $this->t('N/A')
          : ($stats['remaining'] > 0 ? $this->t('In progress') : $this->t('All registered ✓'));
        $rows[] = [
          'data' => [
            ['data' => $stats['label']],
            ['data' => $stats['total']],
            ['data' => $stats['registered']],
            ['data' => $stats['remaining'], 'class' => [$stats['remaining'] > 0 ? 'color-warning' : 'color-success']],
            ['data' => $status],
          ],
        ];
      }
    }

    // Render the status table first (not inside a list).
    $form['status']['table'] = [
      '#type' => 'table',
      '#header' => $header,
      '#rows' => $rows,
    ];

    // Then render supplemental info as a list below the table.
    $status_list_items = [];

    if ($queue_count > 0) {
      $status_list_items[] = $this->t('Queue items pending: <strong>@count</strong>', ['@count' => $queue_count]);
    }

    if ($is_enhanced_mode) {
      $status_list_items[] = $this->t('Enhanced mode: <strong>Enabled</strong> (tracking content entity references)');
    }
    else {
      $status_list_items[] = $this->t('Enhanced mode: <strong>Disabled</strong> (media entities only)');
    }

    $form['status']['info'] = [
      '#theme' => 'item_list',
      '#items' => $status_list_items,
    ];

    // Actions section.
    $form['actions'] = [
      '#type' => 'actions',
    ];

    $form['actions']['register'] = [
      '#type' => 'submit',
      '#value' => $this->t('Register Integration Links'),
      '#button_type' => 'primary',
    ];

    $form['help'] = [
      '#type' => 'details',
      '#title' => $this->t('How it works'),
      '#open' => FALSE,
    ];

    $help_items = [
      $this->t("This process queues all DAM media items for integration link registration."),
      $this->t("If enhanced mode is enabled, content entities referencing DAM assets will also be processed."),
      $this->t("Processing is handled via Drupal's Batch API with a progress bar."),
      $this->t("Integration links are registered with Acquia DAM via their API."),
      $this->t('You can also use Drush commands: <code>drush adqil</code> to queue and <code>drush adpilq</code> to process.'),
    ];

    $form['help']['info'] = [
      '#theme' => 'item_list',
      '#items' => $help_items,
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state): void {
    $batch = [
      'title' => $this->t('Registering Integration Links...'),
      'init_message' => $this->t('Initializing...'),
      'progress_message' => $this->t('Processing @current of @total batches.'),
      'error_message' => $this->t('An error occurred during processing.'),
      'operations' => [
        [
          [static::class, 'batchProcessMediaEntities'],
          [],
        ],
        [
          [static::class, 'batchProcessContentEntities'],
          [],
        ],
        [
          [static::class, 'batchProcessQueue'],
          [],
        ],
      ],
      'finished' => [static::class, 'batchFinished'],
    ];

    batch_set($batch);
  }

  /**
   * Batch operation: Process media entities.
   *
   * @param array|\ArrayAccess $context
   *   The batch context.
   */
  public static function batchProcessMediaEntities(&$context): void {
    if (!isset($context['sandbox']['progress'])) {
      $context['sandbox']['progress'] = 0;
      $context['results']['media_queued'] = 0;
      $context['results']['media_processed'] = 0;
    }

    // Get service from container (cannot pass service objects to batch).
    $processor = \Drupal::service('acquia_dam.integration_links_batch_processor');

    // Process without closure callback (closures cannot be serialized).
    $results = $processor->processMediaEntities(50, NULL, NULL);

    $context['results']['media_queued'] = $results['total_queued'];
    $context['results']['media_processed'] = $results['total_processed'];
    $context['message'] = t('Queued @count media items for integration link registration.', [
      '@count' => $results['total_queued'],
    ]);
  }

  /**
   * Batch operation: Process content entities.
   *
   * @param array|\ArrayAccess $context
   *   The batch context.
   */
  public static function batchProcessContentEntities(&$context): void {
    // Get service from container.
    $processor = \Drupal::service('acquia_dam.integration_links_batch_processor');

    if (!$processor->isEnhancedModeEnabled()) {
      $context['results']['content_queued'] = 0;
      $context['results']['content_processed'] = 0;
      return;
    }

    // Process without closure callback.
    $results = $processor->processContentEntities(50, NULL);

    $context['results']['content_queued'] = $results['content_queued'];
    $context['results']['content_processed'] = $results['content_processed'];
    $context['message'] = t('Queued @count content entity references.', [
      '@count' => $results['content_queued'],
    ]);
  }

  /**
   * Batch operation: Process the queue.
   *
   * @param array|\ArrayAccess $context
   *   The batch context.
   */
  public static function batchProcessQueue(&$context): void {
    // Get service from container.
    $queue_service = \Drupal::service('acquia_dam.integration_links_queue_service');

    // Process without closure callback.
    $results = $queue_service->processQueue(0, NULL);

    $context['results']['queue_processed'] = $results['processed'];
    $context['results']['queue_failed'] = $results['failed'];
    $context['results']['queue_skipped'] = $results['skipped'];
    $context['message'] = t('Processed @count queue items.', [
      '@count' => $results['processed'],
    ]);
  }

  /**
   * Batch finished callback.
   *
   * @param bool $success
   *   Whether the batch completed successfully.
   * @param array $results
   *   The batch results.
   * @param array $operations
   *   The operations that were performed.
   */
  public static function batchFinished($success, array $results, array $operations): void {
    $messenger = \Drupal::messenger();

    if ($success) {
      $messenger->addStatus(t('Integration links registration completed successfully!'));
      $messenger->addStatus(t('Media items queued: @count', ['@count' => $results['media_queued'] ?? 0]));

      if (!empty($results['content_queued'])) {
        $messenger->addStatus(t('Content entity references queued: @count', ['@count' => $results['content_queued']]));
      }

      $messenger->addStatus(t('Queue items processed: @count', ['@count' => $results['queue_processed'] ?? 0]));

      if (!empty($results['queue_failed'])) {
        $messenger->addStatus(t('Queue items failed: @count', ['@count' => $results['queue_failed']]));
      }

      if (!empty($results['queue_skipped'])) {
        $messenger->addStatus(t('Queue items skipped: @count', ['@count' => $results['queue_skipped']]));
      }
    }
    else {
      $messenger->addError(t('An error occurred during integration links registration.'));
    }
  }

}
