<?php

namespace Drupal\miniorange_2fa\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Symfony\Component\HttpFoundation\Response;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\miniorange_2fa\MoAuthUtilities;
use Drupal\Component\Utility\Html;
use \Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Defines the 2FA/MFA logs report form.
 */
class ReportSection extends FormBase
{

  /**
   * The date formatter service.
   *
   * @var \Drupal\Core\Datetime\DateFormatterInterface
   */
  protected $dateFormatter;

  /**
   * Constructs a new MoAuthReportSection instance.
   *
   * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
   *   The date formatter service.
   */
  public function __construct(DateFormatterInterface $date_formatter)
  {
    $this->dateFormatter = $date_formatter;
  }

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

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

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state): array
  {
    
    $utilities = new MoAuthUtilities();
    $registration_required = !$utilities::isCustomerRegistered();
    $request = \Drupal::request();
    if ($registration_required) {
      $form['header'] = [
        '#markup' => $this->t('<div class="mo_2fa_register_message"><p>You need to <a href=":url">Register/Login</a> with miniOrange before using this module.</p></div>', [
          ':url' => Url::fromRoute('miniorange_2fa.customer_setup')->toString(),
        ]),
      ];
    }
    $form['#attached']['library'][] = 'miniorange_2fa/miniorange_2fa.admin';
    $form['#attached']['library'][] = 'miniorange_2fa/miniorange_2fa.license';
    
    $filters = [
      'username' => $request->query->get('username', ''),
      'event_type' => $request->query->get('event_type', ''),
      'status' => $request->query->get('status', ''),
    ];

    $has_filters = !empty($filters['username']) || !empty($filters['event_type']) || !empty($filters['status']);

    $form['filters'] = $this->buildFiltersSection($filters, $registration_required, $has_filters);
    $form['results'] = $this->buildResultsTable($filters, $registration_required);

    return $form;
  }

  /**
   * Builds the filters section of the form.
   *
   * @param array $filters
   *   The current filter values.
   *
   * @return array
   *   The form elements for filters.
   */
  protected function buildFiltersSection(array $filters, $registration_required, $show_reset): array
  {
    $filters_section =  [
      '#type' => 'fieldset',
      '#title' => $this->t('Filter Logs'),
      '#attributes' => ['class' => ['moauthReportFilters']],
      '#collapsible' => TRUE,
      '#collapsed' => FALSE,
      'container' => [
        '#type' => 'container',
        '#attributes' => [
          'style' => 'display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap;',
        ],
        'username' => [
          '#type' => 'textfield',
          '#title' => $this->t('Username'),
          '#default_value' => $filters['username'],
          '#disabled' => $registration_required,
        ],
        'event_type' => [
          '#type' => 'select',
          '#title' => $this->t('Event Type'),
          '#options' => [
            '' => $this->t('- Any -'),
            'login_attempt' => $this->t('Login Attempt'),
            'mfa_status' => $this->t('MFA Status'),
          ],
          '#default_value' => $filters['event_type'],
          '#disabled' => $registration_required,
        ],
        'status' => [
          '#type' => 'select',
          '#title' => $this->t('Status'),
          '#options' => [
            '' => $this->t('- Any -'),
            'success' => $this->t('Success'),
            'failure' => $this->t('Failure'),
            'enabled' => $this->t('Enabled'),
            'disabled' => $this->t('Disabled'),
          ],
          '#default_value' => $filters['status'],
          '#disabled' => $registration_required,
        ],
        'submit' => [
          '#type' => 'submit',
          '#value' => $this->t('Apply'),
          '#attributes' => [
            'class' => ['button'],
            'style' => 'margin-bottom:25px;',
          ],
          '#disabled' => $registration_required,
        ],
        'reset' => [
          '#type' => 'submit',
          '#value' => $this->t('Reset'),
          '#submit' => ['::resetLogsSubmit'],
          '#attributes' => [
            'class' => ['button'],
            'style' => 'margin-bottom:25px;',
          ],
          '#disabled' => $registration_required,
        ],
        'download' => [
          '#type' => 'submit',
          '#value' => $this->t('Download'),
          '#submit' => ['::downloadCsvSubmit'],
          '#attributes' => [
            'class' => ['button button--primary'],
            'style' => 'margin-bottom:25px;',
          ],
          '#disabled' => $registration_required,
        ],
      ],
    ];
    if (!$registration_required) {
        $filters_section['container']['delete'] = [
            '#type' => 'link',
            '#title' => $this->t('Delete'),
            '#url' => Url::fromRoute('miniorange_2fa.delete_logs_confirm'),
            '#attributes' => [
                'class' => ['button button--danger'],
                'style' => 'margin-bottom:25px;',
            ],
        ];
    }
    return $filters_section;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state): void
  {
    $form_state->setRedirect('miniorange_2fa.report_section', [], [
      'query' => [
        'username' => trim($form_state->getValue('username')),
        'event_type' => $form_state->getValue('event_type'),
        'status' => $form_state->getValue('status'),
      ],
    ]);
  }

  /**
   * Submit handler for CSV download.
   */
  public function downloadCsvSubmit(array &$form, FormStateInterface $form_state): void
  {
    try {
      $filters = [
        'username' => trim($form_state->getValue('username')),
        'event_type' => $form_state->getValue('event_type'),
        'status' => $form_state->getValue('status'),
      ];

      $query = $this->buildBaseQuery($filters);
      $results = $query->execute();

      $filename = '2fa_logs_' . date('Ymd_His') . '.csv';
      $response = new Response();
      $response->headers->set('Content-Type', 'text/csv');
      $response->headers->set('Content-Disposition', 'attachment; filename="' . $filename . '"');

      $handle = fopen('php://temp', 'r+');
      fputcsv($handle, ['UID', 'Username', 'Event Type', 'Status', 'Message', 'Timestamp']);

      foreach ($results as $record) {
        fputcsv($handle, [
          $record->uid,
          $record->username,
          $record->event_type,
          $record->status,
          $record->message,
          $this->dateFormatter->format($record->timestamp, 'short'),
        ]);
      }

      rewind($handle);
      $response->setContent(stream_get_contents($handle));
      fclose($handle);

      $response->send();
      exit;
    } catch (\Exception $e) {
      \Drupal::messenger()->addError($this->t('Error generating CSV: @error', ['@error' => $e->getMessage()]));
    }
  }

  /**
   * Submit handler for resetting filters.
   */
  public function resetLogsSubmit(array &$form, FormStateInterface $form_state): void
  {
    $form_state->setRedirect('miniorange_2fa.report_section');
  }

  /**
   * Builds the base query for logs with filters.
   *
   * @param array $filters
   *   The filter values.
   *
   * @return \Drupal\Core\Database\Query\Select
   *   The query object.
   */
  protected function buildBaseQuery(array $filters)
  {
    $query = \Drupal::database()->select('miniorange_2fa_logs', 'l')
      ->fields('l', ['id', 'uid', 'username', 'event_type', 'status', 'timestamp', 'message'])
      ->orderBy('timestamp', 'DESC');

    if (!empty($filters['username'])) {
      $query->condition('username', $filters['username'], '=');
    }
    if (!empty($filters['event_type'])) {
      $query->condition('event_type', $filters['event_type']);
    }
    if (!empty($filters['status'])) {
      $query->condition('status', $filters['status']);
    }

    return $query;
  }

  /**
   * Build the results table.
   *
   * @param array $filters
   *   The filter values.
   *
   * @return array
   *   The table render array.
   */
 protected function buildResultsTable(array $filters, $registration_required): array {
   
   if($registration_required){
     return [
       '#markup' => $this->t('Register/Login with miniOrange to view logs')
     ];
   }
   
   $limit = 50;
   $query = $this->buildBaseQuery($filters)
     ->extend('Drupal\Core\Database\Query\PagerSelectExtender')
     ->limit($limit);

   $results = $query->execute();

   $rows = [];
   foreach ($results as $record) {
     $rows[] = [
       Html::escape($record->uid),
       Html::escape($record->username),
       Html::escape($record->event_type),
       Html::escape($record->status),
       Html::escape($record->message),
       Html::escape($this->dateFormatter->format($record->timestamp, 'short')),
     ];
   }

   return [
     'logs_table' => [
       '#type' => 'table',
       '#header' => [
         $this->t('UID'),
         $this->t('Username'),
         $this->t('Event Type'),
         $this->t('Status'),
         $this->t('Message'),
         $this->t('Date'),
       ],
       '#rows' => $rows,
       '#empty' => $this->t('Sorry, no logs found.'),
     ],
     'pager' => [
       '#type' => 'pager',
     ],
   ];
}
}
