<?php

namespace PloverCRM\Modules\Integrations\Providers;

/**
 * MetForm Provider
 * 
 * Integrates with MetForm (Elementor Form Builder)
 */
class MetFormProvider implements DataSourceProviderInterface
{
  private $eventCallback;

  public function getKey(): string
  {
    return 'metform';
  }

  public function getName(): string
  {
    return 'MetForm';
  }

  public function getIcon(): string
  {
    return 'metform.svg';
  }

  public function getCategory(): string
  {
    return 'forms';
  }

  public function isAvailable(): bool
  {
    return defined('METFORM_VERSION') || class_exists('\MetForm\Plugin');
  }

  public function getSupportedEvents(): array
  {
    return [
      ['key' => 'submission', 'label' => 'Form Submission'],
    ];
  }

  public function getSources(): array
  {
    if (!$this->isAvailable()) {
      return [];
    }

    $forms = get_posts([
      'post_type' => 'metform-form',
      'posts_per_page' => -1,
      'post_status' => 'publish',
    ]);

    return array_map(fn($form) => [
      'id' => (string) $form->ID,
      'title' => $form->post_title,
    ], $forms);
  }

  public function getSourceFields(string $sourceId): array
  {
    if (!$this->isAvailable()) {
      return [];
    }

    $formId = intval($sourceId);
    $elementorData = get_post_meta($formId, '_elementor_data', true);

    if (empty($elementorData)) {
      return [];
    }

    $elements = json_decode($elementorData);

    if (!is_array($elements)) {
      return [];
    }

    return $this->extractFields($elements);
  }

  public function registerEventListener(callable $callback): void
  {
    $this->eventCallback = $callback;
    add_action('metform_after_store_form_data', [$this, 'handleSubmission'], 20, 4);
  }

  /**
   * Handle MetForm submission
   * 
   * @param int $formId Form ID
   * @param array $formData Submitted form data
   * @param array $formSettings Form settings
   * @param array $attributes Additional attributes
   */
  public function handleSubmission($formId, $formData, $formSettings, $attributes): void
  {
    unset($formSettings, $attributes); // Not used

    if (!$this->eventCallback) {
      return;
    }

    // Normalize form data - remove internal fields
    $normalized = [];
    foreach ($formData as $key => $value) {
      // Skip internal MetForm fields
      if (in_array($key, ['id', 'form_nonce', 'action', 'g-recaptcha-response', 'g-recaptcha-response-v3', 'mf-captcha-challenge'])) {
        continue;
      }

      // Handle array values
      if (is_array($value)) {
        $normalized[$key] = implode(', ', $value);
      } else {
        $normalized[$key] = $value;
      }
    }

    call_user_func($this->eventCallback, $this->getKey(), (string) $formId, $normalized);
  }

  /**
   * Extract form fields from Elementor data
   */
  private function extractFields(array $elements): array
  {
    $fields = [];
    $widgetTypes = $this->getInputWidgetTypes();

    // Widgets that use fixed names (the widget type IS the field name)
    $fixedNameWidgets = [
      'mf-listing-fname' => 'mf-listing-fname',
      'mf-listing-lname' => 'mf-listing-lname',
      'mf-listing-optin' => 'mf-listing-optin',
    ];

    foreach ($elements as $element) {
      // Recursively check nested elements
      if (!empty($element->elements) && is_array($element->elements)) {
        $nestedFields = $this->extractFields($element->elements);
        $fields = array_merge($fields, $nestedFields);
        continue;
      }

      // Check if this is a form input widget
      if (!isset($element->elType) || $element->elType !== 'widget') {
        continue;
      }

      $widgetType = $element->widgetType ?? '';

      // Skip non-input widgets
      if (!in_array($widgetType, $widgetTypes)) {
        continue;
      }

      $settings = $element->settings ?? new \stdClass();
      $inputName = $settings->mf_input_name ?? '';
      $inputLabel = $settings->mf_input_label ?? '';

      // For fixed name widgets, use the widget type as the field name if not set
      if (empty($inputName) && isset($fixedNameWidgets[$widgetType])) {
        $inputName = $fixedNameWidgets[$widgetType];
      }

      if (empty($inputName)) {
        continue;
      }

      $fields[] = [
        'key' => $inputName,
        'label' => $inputLabel ?: ucfirst(str_replace(['_', '-'], ' ', $inputName)),
        'type' => $this->mapWidgetType($widgetType),
      ];
    }

    return $fields;
  }

  /**
   * Get list of MetForm input widget types
   */
  private function getInputWidgetTypes(): array
  {
    return [
      'mf-text',
      'mf-email',
      'mf-number',
      'mf-textarea',
      'mf-telephone',
      'mf-url',
      'mf-password',
      'mf-select',
      'mf-multi-select',
      'mf-checkbox',
      'mf-radio',
      'mf-switch',
      'mf-range',
      'mf-date',
      'mf-time',
      'mf-file-upload',
      'mf-rating',
      'mf-listing-fname',
      'mf-listing-lname',
      'mf-listing-optin',
      'mf-gdpr-consent',
      // Pro widgets
      'mf-signature',
      'mf-image-select',
      'mf-toggle-select',
      'mf-simple-repeater',
      'mf-color-picker',
      'mf-calculation',
      'mf-like-dislike',
      'mf-credit-card',
      'mf-mobile',
      'mf-map-location',
    ];
  }

  /**
   * Map MetForm widget type to standard field type
   */
  private function mapWidgetType(string $widgetType): string
  {
    $map = [
      'mf-text' => 'text',
      'mf-email' => 'email',
      'mf-number' => 'number',
      'mf-textarea' => 'textarea',
      'mf-telephone' => 'phone',
      'mf-url' => 'url',
      'mf-password' => 'text',
      'mf-select' => 'select',
      'mf-multi-select' => 'select',
      'mf-checkbox' => 'checkbox',
      'mf-radio' => 'radio',
      'mf-switch' => 'checkbox',
      'mf-range' => 'number',
      'mf-date' => 'date',
      'mf-time' => 'time',
      'mf-file-upload' => 'file',
      'mf-rating' => 'number',
      'mf-listing-fname' => 'text',
      'mf-listing-lname' => 'text',
      'mf-listing-optin' => 'checkbox',
      'mf-gdpr-consent' => 'checkbox',
      'mf-signature' => 'text',
      'mf-image-select' => 'select',
      'mf-toggle-select' => 'select',
      'mf-color-picker' => 'text',
      'mf-calculation' => 'number',
      'mf-like-dislike' => 'text',
      'mf-mobile' => 'phone',
    ];

    return $map[$widgetType] ?? 'text';
  }
}
