<?php
/**
 * @license GPL-2.0-or-later
 * @link    https://wordpress.org/plugins/pressio-crm
 */
namespace PressioCRM\Integrations;

defined( 'ABSPATH' ) || exit;

use PressioCRM\Models\ContactModel;
use PressioCRM\Models\ActivityModel;
use PressioCRM\Models\IntegrationModel;

class FluentformsIntegration {

	public function slug(): string {
		return 'fluentforms';
	}

	/**
	 * Called by IntegrationManager::register().
	 * Hooks into the Fluent Forms submission pipeline.
	 */
	public function register(): void {
		// Fires after a Fluent Forms entry is saved successfully.
		// Params: int $entry_id, array $form_data, object $form (id, title, …)
		add_action( 'fluentform/submission_inserted', [ $this, 'handle_submission' ], 10, 3 );
	}

	// -------------------------------------------------------------------------
	// Handle submission
	// -------------------------------------------------------------------------

	/**
	 * @param int    $entry_id  Fluent Forms entry ID (unused — we only need form data).
	 * @param array  $form_data Flat/nested array of submitted values keyed by field name.
	 * @param object $form      Fluent Forms form object: id (int), title (string).
	 */
	public function handle_submission( int $entry_id, array $form_data, object $form ): void {
		$form_id = (string) $form->id;
		$mapping = $this->get_mapping( $form_id );

		if ( ! $mapping || ! $mapping->is_active ) {
			return;
		}

		$config = json_decode( $mapping->config ?? '{}', true );
		if ( ! is_array( $config ) || empty( $config ) ) {
			return;
		}

		// Build contact data from the saved field mapping.
		$contact_data  = [ 'source' => 'fluentforms' ];
		$string_fields = [ 'email', 'first_name', 'last_name', 'phone', 'company' ];

		foreach ( $string_fields as $field ) {
			if ( empty( $config[ $field ] ) ) {
				continue;
			}

			$value = $this->extract_value( $form_data, $config[ $field ] );

			if ( '' === $value ) {
				continue;
			}

			$contact_data[ $field ] = 'email' === $field
				? sanitize_email( $value )
				: sanitize_text_field( $value );
		}

		// Email is required.
		if ( empty( $contact_data['email'] ) ) {
			return;
		}

		$existing = ContactModel::find_by_email( $contact_data['email'] );
		$is_new   = false;

		if ( $existing ) {
			// Only fill in fields that are currently empty on the existing contact.
			$update_data = [];
			foreach ( $contact_data as $key => $value ) {
				if ( 'source' === $key || 'email' === $key ) {
					continue;
				}
				if ( '' !== $value && empty( $existing->{$key} ) ) {
					$update_data[ $key ] = $value;
				}
			}

			if ( ! empty( $update_data ) ) {
				$existing->update( $update_data );
			}

			$contact_id = (int) $existing->id;
		} else {
			$contact    = ContactModel::create( $contact_data );
			$contact_id = (int) $contact->id;
			$is_new     = true;
		}

		// New contacts: ContactModel::create() already fires contact_created_from_form.
		// Returning contacts: log the repeat submission as an activity.
		if ( ! $is_new ) {
			ActivityModel::log( [
				'contact_id' => $contact_id,
				'type'       => 'contact_created_from_form',
				'title'      => sprintf(
					/* translators: %s: Fluent Forms form title */
					__( 'Submitted form: %s', 'pressio-crm' ),
					sanitize_text_field( $form->title )
				),
				'meta'       => [
					'source'    => 'fluentforms',
					'form_name' => sanitize_text_field( $form->title ),
					'form_id'   => $form_id,
				],
			] );
		}

		do_action( 'pressio_crm_contact_created_from_form', $contact_id, 'fluentforms', $form_data );
	}

	// -------------------------------------------------------------------------
	// Helpers
	// -------------------------------------------------------------------------

	/**
	 * Resolve a field path from form_data, supporting bracket notation.
	 *
	 * Fluent Forms name fields use "names[first_name]" / "names[last_name]".
	 * Simple fields just use "email", "phone", etc.
	 */
	private function extract_value( array $data, string $field_path ): string {
		if ( preg_match( '/^([^\[]+)\[([^\]]+)\]$/', $field_path, $matches ) ) {
			$parent = $matches[1];
			$child  = $matches[2];
			$value  = $data[ $parent ][ $child ] ?? '';
		} else {
			$value = $data[ $field_path ] ?? '';
		}

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

		return trim( (string) $value );
	}

	/** Only returns the mapping if it is active — used at submission time. */
	private function get_mapping( string $form_id ): ?IntegrationModel {
		return IntegrationModel::get_for_object( 'fluentforms', $form_id );
	}
}
