<?php

namespace PloverCRM\Modules\Integrations\Providers;

/**
 * WS Form Provider
 */
class WSFormProvider implements DataSourceProviderInterface
{
  private $eventCallback;

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

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

  public function getIcon(): string
  {
    return 'ws-form.svg';
  }

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

  public function isAvailable(): bool
  {
    return defined('WS_FORM_VERSION') || class_exists('WS_Form_Form');
  }

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

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

    // Use WS Form helper function if available
    if (function_exists('wsf_form_get_all')) {
      $forms = wsf_form_get_all(true); // Get published forms only

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

      // wsf_form_get_all returns arrays, not objects
      return array_map(function ($form) {
        $id = is_array($form) ? ($form['id'] ?? '') : ($form->id ?? '');
        $label = is_array($form) ? ($form['label'] ?? $form['name'] ?? '') : ($form->label ?? $form->name ?? '');
        return [
          'id' => (string) $id,
          'title' => !empty($label) ? $label : 'Form ' . $id,
        ];
      }, $forms);
    }

    // Fallback: Use WS_Form_Form class directly
    if (!class_exists('WS_Form_Form')) {
      return [];
    }

    $wsFormForm = new \WS_Form_Form();
    $forms = $wsFormForm->get_all(true);

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

    return array_map(function ($form) {
      $id = is_array($form) ? ($form['id'] ?? '') : ($form->id ?? '');
      $label = is_array($form) ? ($form['label'] ?? $form['name'] ?? '') : ($form->label ?? $form->name ?? '');
      return [
        'id' => (string) $id,
        'title' => !empty($label) ? $label : 'Form ' . $id,
      ];
    }, $forms);
  }

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

    // Use WS Form helper function to get form object with all fields
    if (!function_exists('wsf_form_get_object')) {
      return [];
    }

    try {
      $formObject = wsf_form_get_object(absint($sourceId), true, true);
    } catch (\Exception $e) {
      return [];
    }

    if (!$formObject || !isset($formObject->groups)) {
      return [];
    }

    $fields = [];

    // Iterate through groups (tabs)
    foreach ($formObject->groups as $group) {
      if (!isset($group->sections)) {
        continue;
      }

      // Iterate through sections
      foreach ($group->sections as $section) {
        if (!isset($section->fields)) {
          continue;
        }

        // Iterate through fields
        foreach ($section->fields as $field) {
          $fieldId = $field->id ?? '';
          $fieldType = $field->type ?? '';
          $label = $field->label ?? '';

          // Skip non-data fields
          if (in_array($fieldType, ['submit', 'reset', 'clear', 'tab_previous', 'tab_next', 'save', 'html', 'divider', 'spacer', 'message', 'progress', 'section_icons', 'recaptcha', 'hcaptcha', 'turnstile'])) {
            continue;
          }

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

          // WS Form uses field_XX format for meta keys
          $fieldKey = 'field_' . $fieldId;

          $fields[] = [
            'key' => $fieldKey,
            'label' => !empty($label) ? $label : 'Field ' . $fieldId,
            'type' => $this->mapFieldType($fieldType),
          ];
        }
      }
    }

    return $fields;
  }

  public function registerEventListener(callable $callback): void
  {
    $this->eventCallback = $callback;
    // Hook into WS Form submission create action
    add_action('wsf_submit_create', [$this, 'handleSubmission'], 20, 1);
  }

  /**
   * Handle WS Form submission
   * 
   * @param \WS_Form_Submit $submit The submit object
   */
  public function handleSubmission($submit): void
  {
    if (!$this->eventCallback) {
      return;
    }

    if (!is_object($submit)) {
      return;
    }

    $formId = $submit->form_id ?? '';

    if (empty($formId)) {
      return;
    }

    // Get the submitted data using get_post_data method
    $postData = [];

    if (method_exists($submit, 'get_post_data')) {
      $postData = $submit->get_post_data();
    } elseif (isset($submit->meta) && is_array($submit->meta)) {
      // Fallback: extract from meta
      foreach ($submit->meta as $key => $metaValue) {
        if (strpos($key, 'field_') === 0) {
          $value = $metaValue['value'] ?? '';
          if (is_array($value)) {
            $value = implode(', ', $value);
          }
          $postData[$key] = $value;
        }
      }
    }

    if (empty($postData)) {
      return;
    }

    // Normalize the data
    $normalized = [];
    foreach ($postData as $key => $value) {
      // Only include field_ keys
      if (strpos($key, 'field_') !== 0) {
        continue;
      }

      if (is_array($value)) {
        $value = implode(', ', $value);
      }

      if ($value !== '' && $value !== null) {
        $normalized[$key] = $value;
      }
    }

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

  private function mapFieldType(string $type): string
  {
    $map = [
      'text' => 'text',
      'textarea' => 'textarea',
      'email' => 'email',
      'url' => 'url',
      'tel' => 'phone',
      'number' => 'number',
      'range' => 'number',
      'date' => 'date',
      'datetime' => 'date',
      'time' => 'time',
      'select' => 'select',
      'radio' => 'radio',
      'checkbox' => 'checkbox',
      'file' => 'file',
      'hidden' => 'hidden',
      'password' => 'text',
      'color' => 'text',
      'rating' => 'number',
      'price' => 'number',
      'price_select' => 'select',
      'price_checkbox' => 'checkbox',
      'price_radio' => 'radio',
      'signature' => 'text',
      'name' => 'text',
      'address' => 'text',
      'legal' => 'checkbox',
      'gdpr' => 'checkbox',
    ];
    return $map[$type] ?? 'text';
  }
}
