<?php

namespace PloverCRM\Modules\Integrations\Providers;

/**
 * Fluent Forms Provider
 */
class FluentFormProvider implements DataSourceProviderInterface
{
  private $eventCallback;

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

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

  public function getIcon(): string
  {
    return 'fluent-forms.svg';
  }

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

  public function isAvailable(): bool
  {
    return defined('FLUENTFORM') || class_exists('\FluentForm\App\Modules\Form\Form');
  }

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

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

    global $wpdb;
    $table = $wpdb->prefix . 'fluentform_forms';

    if ($wpdb->get_var("SHOW TABLES LIKE '$table'") !== $table) {
      return [];
    }

    $forms = $wpdb->get_results(
      "SELECT id, title FROM $table WHERE status = 'published' ORDER BY id DESC"
    );

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

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

    global $wpdb;
    $table = $wpdb->prefix . 'fluentform_forms';

    $form = $wpdb->get_row($wpdb->prepare(
      "SELECT form_fields FROM $table WHERE id = %d",
      intval($sourceId)
    ));

    if (!$form || empty($form->form_fields)) {
      return [];
    }

    $formFields = json_decode($form->form_fields, true);
    if (!$formFields || !isset($formFields['fields'])) {
      return [];
    }

    return $this->extractFields($formFields['fields']);
  }

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

  public function handleSubmission($entryId, $formData, $form): void
  {
    unset($entryId); // Not used, but required by hook signature

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

    $normalized = [];
    foreach ($formData as $key => $value) {
      if (is_array($value)) {
        foreach ($value as $subKey => $subValue) {
          $normalized[$key . '.' . $subKey] = $subValue;
        }
      }
      $normalized[$key] = $value;
    }

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

  private function extractFields(array $fields, string $prefix = ''): array
  {
    $extracted = [];

    foreach ($fields as $field) {
      $element = $field['element'] ?? '';
      $attributes = $field['attributes'] ?? [];
      $settings = $field['settings'] ?? [];

      if (in_array($element, ['custom_html', 'section_break', 'form_step', 'recaptcha', 'hcaptcha', 'turnstile'])) {
        continue;
      }

      if ($element === 'container') {
        foreach ($field['columns'] ?? [] as $column) {
          $extracted = array_merge($extracted, $this->extractFields($column['fields'] ?? [], $prefix));
        }
        continue;
      }

      $name = $attributes['name'] ?? '';
      if (empty($name)) {
        continue;
      }

      $fullKey = $prefix ? $prefix . '.' . $name : $name;
      $label = $settings['label'] ?? $settings['admin_field_label'] ?? ucfirst(str_replace('_', ' ', $name));

      // Handle composite fields (name, address) - only add sub-fields, not the parent
      if ($element === 'input_name' || $element === 'address') {
        $hasVisibleSubFields = false;
        foreach ($field['fields'] ?? [] as $subKey => $subField) {
          if (!empty($subField['settings']['visible'])) {
            $hasVisibleSubFields = true;
            $extracted[] = [
              'key' => $name . '.' . $subKey,
              'label' => $label . ' (' . ($subField['settings']['label'] ?? ucfirst($subKey)) . ')',
              'type' => 'text',
            ];
          }
        }
        // If no visible sub-fields, add the parent field as a simple field
        if (!$hasVisibleSubFields) {
          $extracted[] = [
            'key' => $fullKey,
            'label' => $label,
            'type' => $this->mapFieldType($element),
          ];
        }
        continue;
      }

      $extracted[] = [
        'key' => $fullKey,
        'label' => $label,
        'type' => $this->mapFieldType($element),
      ];
    }

    return $extracted;
  }

  private function mapFieldType(string $element): string
  {
    $map = [
      'input_text' => 'text',
      'input_email' => 'email',
      'input_number' => 'number',
      'input_url' => 'url',
      'textarea' => 'textarea',
      'select' => 'select',
      'input_radio' => 'radio',
      'input_checkbox' => 'checkbox',
      'input_date' => 'date',
      'input_file' => 'file',
      'phone' => 'phone',
    ];
    return $map[$element] ?? 'text';
  }
}
