<?php

namespace PloverCRM\Modules\Integrations\Providers;

/**
 * WPForms Provider
 */
class WPFormsProvider implements DataSourceProviderInterface
{
  private $eventCallback;

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

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

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

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

  public function isAvailable(): bool
  {
    return defined('WPFORMS_VERSION') || function_exists('wpforms');
  }

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

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

    // Use WPForms API to get forms
    if (function_exists('wpforms')) {
      $forms = wpforms()->form->get('', ['post_status' => 'publish']);

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

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

    return [];
  }


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

    $form = wpforms()->form->get(absint($sourceId), ['content_only' => true]);

    if (empty($form) || !isset($form['fields'])) {
      return [];
    }

    $extracted = [];

    foreach ($form['fields'] as $field) {
      $fieldId = $field['id'] ?? '';
      $fieldType = $field['type'] ?? '';
      $label = $field['label'] ?? ucfirst(str_replace('_', ' ', $fieldType));

      // Skip non-data fields
      if (in_array($fieldType, ['html', 'divider', 'pagebreak', 'captcha', 'turnstile'])) {
        continue;
      }

      // Handle name field based on format
      if ($fieldType === 'name') {
        $format = $field['format'] ?? 'first-last';

        if ($format === 'simple') {
          // Simple format - single field
          $extracted[] = [
            'key' => $fieldId,
            'label' => $label,
            'type' => 'text',
          ];
        } else {
          // Expanded formats (first-last, first-middle-last)
          $extracted[] = [
            'key' => $fieldId . '.first',
            'label' => $label . ' (First)',
            'type' => 'text',
          ];

          if ($format === 'first-middle-last') {
            $extracted[] = [
              'key' => $fieldId . '.middle',
              'label' => $label . ' (Middle)',
              'type' => 'text',
            ];
          }

          $extracted[] = [
            'key' => $fieldId . '.last',
            'label' => $label . ' (Last)',
            'type' => 'text',
          ];
        }
        continue;
      }

      // Handle address field
      if ($fieldType === 'address') {
        $subfields = [
          'address1' => 'Address Line 1',
          'address2' => 'Address Line 2',
          'city' => 'City',
          'state' => 'State / Province',
          'postal' => 'ZIP / Postal Code',
          'country' => 'Country',
        ];

        foreach ($subfields as $subKey => $subLabel) {
          $extracted[] = [
            'key' => $fieldId . '.' . $subKey,
            'label' => $label . ' (' . $subLabel . ')',
            'type' => 'text',
          ];
        }
        continue;
      }

      // Regular fields
      $extracted[] = [
        'key' => $fieldId,
        'label' => $label,
        'type' => $this->mapFieldType($fieldType),
      ];
    }

    return $extracted;
  }

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

  /**
   * Handle WPForms submission
   * 
   * @param array $fields    Formatted field data
   * @param array $entry     Raw form submission data
   * @param array $form_data Form data and settings
   * @param int   $entry_id  Entry ID
   */
  public function handleSubmission($fields, $entry, $form_data, $entry_id): void
  {
    unset($entry, $entry_id); // Not used, but required by hook signature

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

    $formId = $form_data['id'] ?? '';
    if (empty($formId)) {
      return;
    }

    // Normalize field data for our system
    // WPForms $fields array has field_id as key, with 'value', 'first', 'middle', 'last' etc.
    $normalized = [];

    foreach ($fields as $fieldId => $fieldData) {
      $fieldType = $fieldData['type'] ?? '';

      // Handle name field with sub-values
      if ($fieldType === 'name') {
        if (!empty($fieldData['first'])) {
          $normalized[$fieldId . '.first'] = $fieldData['first'];
        }
        if (!empty($fieldData['middle'])) {
          $normalized[$fieldId . '.middle'] = $fieldData['middle'];
        }
        if (!empty($fieldData['last'])) {
          $normalized[$fieldId . '.last'] = $fieldData['last'];
        }
      }

      // Handle address field with sub-values
      if ($fieldType === 'address') {
        foreach (['address1', 'address2', 'city', 'state', 'postal', 'country'] as $subKey) {
          if (!empty($fieldData[$subKey])) {
            $normalized[$fieldId . '.' . $subKey] = $fieldData[$subKey];
          }
        }
      }

      // Always include the main value
      if (isset($fieldData['value'])) {
        $normalized[$fieldId] = $fieldData['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',
      'number' => 'number',
      'phone' => 'phone',
      'date-time' => 'date',
      'select' => 'select',
      'radio' => 'radio',
      'checkbox' => 'checkbox',
      'file-upload' => 'file',
      'payment-single' => 'text',
      'payment-multiple' => 'text',
      'payment-checkbox' => 'text',
      'payment-select' => 'text',
      'payment-total' => 'text',
    ];
    return $map[$type] ?? 'text';
  }
}
