<?php

namespace PloverCRM\Modules\Integrations\Providers;

/**
 * Forminator Provider
 * 
 * Integrates with Forminator Forms plugin
 */
class ForminatorProvider implements DataSourceProviderInterface
{
  private $eventCallback;

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

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

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

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

  public function isAvailable(): bool
  {
    return defined('FORMINATOR_VERSION') || class_exists('Forminator');
  }

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

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

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

    $sources = [];
    foreach ($forms as $form) {
      $title = $form->post_title;

      // Try to get the actual form name from Forminator model
      if (class_exists('Forminator_Form_Model')) {
        $model = \Forminator_Form_Model::model()->load($form->ID);
        if ($model && !empty($model->settings['formName'])) {
          $title = $model->settings['formName'];
        }
      }

      $sources[] = [
        'id' => (string) $form->ID,
        'title' => $title,
      ];
    }

    return $sources;
  }

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

    if (!class_exists('Forminator_Form_Model')) {
      return [];
    }

    $formId = intval($sourceId);
    $model = \Forminator_Form_Model::model()->load($formId);

    if (!$model) {
      return [];
    }

    $fields = [];
    $formFields = $model->get_fields();

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

    foreach ($formFields as $field) {
      $fieldArray = $field->to_formatted_array();
      $fieldType = $fieldArray['type'] ?? '';

      // Skip non-input fields
      if (in_array($fieldType, ['html', 'page-break', 'section', 'captcha', 'stripe', 'stripe-ocs', 'paypal', 'group'], true)) {
        continue;
      }

      $elementId = $fieldArray['element_id'] ?? '';
      $fieldLabel = $fieldArray['field_label'] ?? '';

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

      // Handle special field types that have sub-fields
      if ($fieldType === 'name') {
        // Check if it's a multiple name field or simple name field
        $isMultiple = !empty($fieldArray['multiple_name']);

        if ($isMultiple) {
          // Multiple name field - has separate first name, last name, etc.
          if (!empty($fieldArray['fname']) && $fieldArray['fname'] !== 'false') {
            $fields[] = [
              'key' => $elementId . '-first-name',
              'label' => ($fieldLabel ?: 'Name') . ' (First)',
              'type' => 'text',
            ];
          }
          if (!empty($fieldArray['lname']) && $fieldArray['lname'] !== 'false') {
            $fields[] = [
              'key' => $elementId . '-last-name',
              'label' => ($fieldLabel ?: 'Name') . ' (Last)',
              'type' => 'text',
            ];
          }
          if (!empty($fieldArray['prefix']) && $fieldArray['prefix'] !== 'false') {
            $fields[] = [
              'key' => $elementId . '-prefix',
              'label' => ($fieldLabel ?: 'Name') . ' (Prefix)',
              'type' => 'text',
            ];
          }
          if (!empty($fieldArray['mname']) && $fieldArray['mname'] !== 'false') {
            $fields[] = [
              'key' => $elementId . '-middle-name',
              'label' => ($fieldLabel ?: 'Name') . ' (Middle)',
              'type' => 'text',
            ];
          }
        } else {
          // Simple name field - single input for full name
          $fields[] = [
            'key' => $elementId,
            'label' => $fieldLabel ?: 'Name',
            'type' => 'text',
          ];
        }
        continue;
      }

      if ($fieldType === 'address') {
        $addressFields = [
          'street_address' => 'Street Address',
          'address_line' => 'Address Line 2',
          'city' => 'City',
          'state' => 'State',
          'zip' => 'ZIP Code',
          'country' => 'Country',
        ];
        foreach ($addressFields as $subKey => $subLabel) {
          $fields[] = [
            'key' => $elementId . '-' . $subKey,
            'label' => ($fieldLabel ?: 'Address') . ' (' . $subLabel . ')',
            'type' => 'text',
          ];
        }
        continue;
      }

      $fields[] = [
        'key' => $elementId,
        'label' => $fieldLabel ?: ucfirst(str_replace(['_', '-'], ' ', $elementId)),
        'type' => $this->mapFieldType($fieldType),
      ];
    }

    return $fields;
  }

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

  /**
   * Handle Forminator form submission
   * 
   * @param \Forminator_Form_Entry_Model $entry Entry model
   * @param int $formId Form ID
   * @param array $fieldDataArray Field data array
   */
  public function handleSubmission($entry, $formId, $fieldDataArray): void
  {
    if (!$this->eventCallback) {
      return;
    }

    // Skip drafts, spam, and abandoned submissions
    if (!empty($entry->is_spam) || $entry->status !== 'active') {
      return;
    }

    // Normalize form data from field_data_array
    $normalized = [];
    foreach ($fieldDataArray as $field) {
      $key = $field['name'] ?? '';
      $value = $field['value'] ?? '';

      // Skip internal fields
      if (in_array($key, ['_forminator_user_ip', '_user_id'], true)) {
        continue;
      }

      // Skip empty keys
      if (empty($key)) {
        continue;
      }

      // Handle array values (like name fields, address fields)
      if (is_array($value)) {
        // Check if it's a name field (has first-name or last-name keys)
        $isNameField = isset($value['first-name']) || isset($value['last-name']) || isset($value['prefix']) || isset($value['middle-name']);

        if ($isNameField) {
          // Flatten name field sub-values
          if (isset($value['prefix']) && $value['prefix'] !== '') {
            $normalized[$key . '-prefix'] = $value['prefix'];
          }
          if (isset($value['first-name']) && $value['first-name'] !== '') {
            $normalized[$key . '-first-name'] = $value['first-name'];
          }
          if (isset($value['middle-name']) && $value['middle-name'] !== '') {
            $normalized[$key . '-middle-name'] = $value['middle-name'];
          }
          if (isset($value['last-name']) && $value['last-name'] !== '') {
            $normalized[$key . '-last-name'] = $value['last-name'];
          }
          continue;
        }

        // Check if it's an address field
        $isAddressField = isset($value['street_address']) || isset($value['city']) || isset($value['state']) || isset($value['zip']) || isset($value['country']);

        if ($isAddressField) {
          foreach ($value as $subKey => $subValue) {
            if ($subValue !== '' && $subValue !== null) {
              $normalized[$key . '-' . $subKey] = is_array($subValue) ? implode(', ', $subValue) : $subValue;
            }
          }
          continue;
        }

        // For other arrays (checkboxes, multi-select), join values
        $stringValues = array_filter($value, function ($v) {
          return is_string($v) || is_numeric($v);
        });
        if (!empty($stringValues)) {
          $normalized[$key] = implode(', ', $stringValues);
        }
      } else {
        // Simple string/number value
        if ($value !== '' && $value !== null) {
          $normalized[$key] = $value;
        }
      }
    }

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

  /**
   * Map Forminator field type to standard field type
   */
  private function mapFieldType(string $fieldType): string
  {
    $map = [
      'text' => 'text',
      'email' => 'email',
      'number' => 'number',
      'textarea' => 'textarea',
      'phone' => 'phone',
      'url' => 'url',
      'password' => 'text',
      'select' => 'select',
      'checkbox' => 'checkbox',
      'radio' => 'radio',
      'date' => 'date',
      'time' => 'time',
      'upload' => 'file',
      'postdata' => 'text',
      'hidden' => 'hidden',
      'calculation' => 'number',
      'currency' => 'number',
      'slider' => 'number',
      'rating' => 'number',
      'gdprcheckbox' => 'checkbox',
      'consent' => 'checkbox',
      'signature' => 'text',
    ];

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