<?php

namespace Drupal\mailjet_webform\Plugin\WebformHandler;

use Drupal\Core\Form\FormStateInterface;
use Drupal\webform\Plugin\WebformHandlerBase;
use Drupal\webform\WebformSubmissionInterface;

/**
 * Adds webform submission email to Mailjet list.
 *
 * @WebformHandler(
 *   id = "mailjet_list",
 *   label = @Translation("Add to Mailjet List"),
 *   category = @Translation("Email Marketing"),
 *   description = @Translation("Adds the submitted email address to a Mailjet contact list."),
 *   cardinality = \Drupal\webform\Plugin\WebformHandlerInterface::CARDINALITY_UNLIMITED,
 *   results = \Drupal\webform\Plugin\WebformHandlerInterface::RESULTS_PROCESSED,
 *   submission = \Drupal\webform\Plugin\WebformHandlerInterface::SUBMISSION_OPTIONAL,
 * )
 */
class MailjetListHandler extends WebformHandlerBase {

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
      'list_id' => '',
      'email_field' => '',
      'name_field' => '',
      'page_field' => '',
      'source_field' => '',
      'double_optin' => TRUE,
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    $form['list_id'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Mailjet List ID'),
      '#description' => $this->t('Enter the Mailjet List ID. You can find this in your Mailjet account under Contacts > Lists.'),
      '#default_value' => $this->configuration['list_id'],
      '#required' => TRUE,
    ];

    // Get webform elements for field selection.
    $elements = $this->getWebform()->getElementsDecodedAndFlattened();
    $email_fields = [];
    $text_fields = [];

    foreach ($elements as $key => $element) {
      if (isset($element['#type']) && $element['#type'] === 'email') {
        $email_fields[$key] = isset($element['#title']) ? $element['#title'] : $key;
      }
      if (isset($element['#type']) && in_array($element['#type'], ['textfield', 'email', 'name', 'hidden'])) {
        $text_fields[$key] = isset($element['#title']) ? $element['#title'] : $key;
      }
    }

    $form['email_field'] = [
      '#type' => 'select',
      '#title' => $this->t('Email Field'),
      '#description' => $this->t('Select the webform field that contains the email address.'),
      '#options' => $email_fields,
      '#default_value' => $this->configuration['email_field'],
      '#required' => TRUE,
      '#empty_option' => $this->t('- Select -'),
    ];

    $form['name_field'] = [
      '#type' => 'select',
      '#title' => $this->t('Name Field (Optional)'),
      '#description' => $this->t('Select the webform field that contains the contact name.'),
      '#options' => $text_fields,
      '#default_value' => $this->configuration['name_field'],
      '#empty_option' => $this->t('- None -'),
    ];

    $form['page_field'] = [
      '#type' => 'select',
      '#title' => $this->t('Page Field (Optional)'),
      '#description' => $this->t('Select the webform field that contains the page information.'),
      '#options' => $text_fields,
      '#default_value' => $this->configuration['page_field'],
      '#empty_option' => $this->t('- None -'),
    ];

    $form['source_field'] = [
      '#type' => 'select',
      '#title' => $this->t('Source Field (Optional)'),
      '#description' => $this->t('Select the webform field that contains the source information.'),
      '#options' => $text_fields,
      '#default_value' => $this->configuration['source_field'],
      '#empty_option' => $this->t('- None -'),
    ];

    $form['double_optin'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Require double opt-in'),
      '#description' => $this->t('If checked, Mailjet will send a confirmation email to the subscriber.'),
      '#default_value' => $this->configuration['double_optin'],
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    parent::submitConfigurationForm($form, $form_state);
    $this->configuration['list_id'] = $form_state->getValue('list_id');
    $this->configuration['email_field'] = $form_state->getValue('email_field');
    $this->configuration['name_field'] = $form_state->getValue('name_field');
    $this->configuration['page_field'] = $form_state->getValue('page_field');
    $this->configuration['source_field'] = $form_state->getValue('source_field');
    $this->configuration['double_optin'] = (bool) $form_state->getValue('double_optin');
  }

  /**
   * {@inheritdoc}
   */
  public function postSave(WebformSubmissionInterface $webform_submission, $update = TRUE) {
    // Only process on new submissions.
    if ($update) {
      return;
    }

    $email_field = $this->configuration['email_field'];
    $name_field = $this->configuration['name_field'];
    $page_field = $this->configuration['page_field'];
    $source_field = $this->configuration['source_field'];
    $list_id = $this->configuration['list_id'];

    if (empty($email_field) || empty($list_id)) {
      $this->getLogger()->error('Mailjet handler is not properly configured.');
      return;
    }

    // Get submission data.
    $data = $webform_submission->getData();

    // Log the submission data for debugging.
    $this->getLogger()->debug('Webform data: @data', [
      '@data' => print_r($data, TRUE),
    ]);

    $email = $data[$email_field] ?? NULL;

    if (empty($email)) {
      $this->getLogger()->error('Email field @field is empty. Available fields: @fields', [
        '@field' => $email_field,
        '@fields' => implode(', ', array_keys($data)),
      ]);
      return;
    }

    // Validate email format.
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
      $this->getLogger()->error('Invalid email format: @email from field @field', [
        '@email' => $email,
        '@field' => $email_field,
      ]);
      return;
    }

    // Get name if configured.
    $name = '';
    if (!empty($name_field) && !empty($data[$name_field])) {
      $name = $data[$name_field];
    }

    // Get page if configured.
    $page = '';
    if (!empty($page_field) && !empty($data[$page_field])) {
      $page = $data[$page_field];
    }

    // Get source if configured.
    $source = '';
    if (!empty($source_field) && !empty($data[$source_field])) {
      $source = $data[$source_field];
    }

    // Add contact to Mailjet list.
    try {
      $contact_data = [
        'Email' => $email,
        'Name' => $name,
        'IsExcludedFromCampaigns' => FALSE,
      ];

      // Add custom properties if available.
      $properties = [];
      if (!empty($page)) {
        $properties['page'] = $page;
      }
      if (!empty($source)) {
        $properties['source'] = $source;
      }
      if (!empty($properties)) {
        $contact_data['Properties'] = $properties;
      }

      // Use Mailjet API to add contact to list.
      $config = \Drupal::config('mailjet_api.settings');

      // Try to get API keys from Key module first.
      $api_key = NULL;
      $api_secret = NULL;

      if (\Drupal::moduleHandler()->moduleExists('key')) {
        $key_repository = \Drupal::service('key.repository');

        $public_key_id = $config->get('api_key_public');
        $secret_key_id = $config->get('api_key_secret');

        if ($public_key_id) {
          $public_key_entity = $key_repository->getKey($public_key_id);
          if ($public_key_entity) {
            $api_key = $public_key_entity->getKeyValue();
          }
        }

        if ($secret_key_id) {
          $secret_key_entity = $key_repository->getKey($secret_key_id);
          if ($secret_key_entity) {
            $api_secret = $secret_key_entity->getKeyValue();
          }
        }
      }

      // Fallback to direct config values if Key module didn't work.
      if (empty($api_key)) {
        $api_key = $config->get('api_key_public');
      }
      if (empty($api_secret)) {
        $api_secret = $config->get('api_key_secret');
      }

      if (empty($api_key) || empty($api_secret)) {
        $this->getLogger()->error('Mailjet API credentials are not configured. Public key: @public, Secret key: @secret', [
          '@public' => $config->get('api_key_public'),
          '@secret' => $config->get('api_key_secret') ? 'configured' : 'missing',
        ]);
        return;
      }

      $mj = new \Mailjet\Client($api_key, $api_secret, TRUE, ['version' => 'v3']);

      // Create or update contact.
      $contact_response = $mj->post(\Mailjet\Resources::$Contact, [
        'body' => $contact_data,
      ]);

      if ($contact_response->success()) {
        $contact_id = $contact_response->getData()[0]['ID'];

        // Add contact to list.
        $list_response = $mj->post(\Mailjet\Resources::$ContactslistManagecontact, [
          'id' => $list_id,
          'body' => [
            'Email' => $email,
            'Action' => $this->configuration['double_optin'] ? 'addnoforce' : 'addforce',
          ],
        ]);

        if ($list_response->success()) {
          $this->getLogger()->notice('Added @email to Mailjet list @list', [
            '@email' => $email,
            '@list' => $list_id,
          ]);
        }
        else {
          $this->getLogger()->error('Failed to add @email to Mailjet list: @error', [
            '@email' => $email,
            '@error' => $list_response->getReasonPhrase(),
          ]);
        }
      }
      else {
        $this->getLogger()->error('Failed to create/update Mailjet contact @email: @error', [
          '@email' => $email,
          '@error' => $contact_response->getReasonPhrase(),
        ]);
      }
    }
    catch (\Exception $e) {
      $this->getLogger()->error('Mailjet API error: @message', ['@message' => $e->getMessage()]);
    }
  }

}
