<?php
// DESCRIPTION: Contact Form 7 integration — registers each CF7 form as a data source,
// captures submissions on wpcf7_mail_sent, and enqueues them for Google Sheets sync.

namespace SheetWise\Integrations;

class ContactForm7 {

	/**
	 * Cached CF7 forms to avoid repeated DB queries
	 *
	 * @since 2.0.0
	 *
	 * @var array|null
	 */
	private $forms_cache = null;

	/**
	 * Initialize CF7 integration hooks
	 *
	 * @since 2.0.0
	 */
	public function __construct() {
		add_filter( 'swise_integration_data_sources', [ $this, 'add_cf7_data_sources' ] );
		add_filter( 'swise_integration_data_source_events', [ $this, 'add_cf7_data_source_events' ] );

		add_action( 'wpcf7_mail_sent', [ $this, 'handle_cf7_submission' ], 10, 1 );

		// Clear form cache when CF7 forms are created, updated, or deleted
		add_action( 'save_post_wpcf7_contact_form', [ $this, 'clear_forms_cache' ] );
	}

	/**
	 * Add CF7 forms as data sources
	 *
	 * @since 2.0.0
	 *
	 * @param array $sources Existing data sources
	 *
	 * @return array
	 */
	public function add_cf7_data_sources( $sources ) {
		$integrations       = swise_get_settings_schema( 'integrations' );
		$saved_integrations = get_option( 'swise_settings_integrations' );

		$cf7_sources = $this->get_cf7_data_sources();

		if ( ! empty( $integrations['fields'] ) ) {
			foreach ( array_keys( $integrations['fields'] ) as $integration ) {
				if ( $integration === 'contact_form_7' && ! empty( $saved_integrations[ $integration ] ) ) {
					$sources = array_merge( $sources, $cf7_sources );
				}
			}
		}

		return $sources;
	}

	/**
	 * Get CF7 data source definitions (one per form)
	 *
	 * @since 2.0.0
	 *
	 * @return array
	 */
	public function get_cf7_data_sources() {
		$sources = [];
		$forms   = $this->get_cf7_forms();

		foreach ( $forms as $form ) {
			$hook_name = 'wpcf7_submit_' . $form->ID;

			$sources[ $hook_name ] = [
				'label'       => sprintf(
					/* translators: %s: CF7 form title */
					__( 'CF7: %s', 'sheet-wise' ),
					$form->post_title
				),
				'num_of_args' => 1,
			];
		}

		return apply_filters( 'swise_integration_data_sources_cf7', $sources );
	}

	/**
	 * Add CF7 data source events (fields for each form)
	 *
	 * @since 2.0.0
	 *
	 * @param array $events Existing data source events
	 *
	 * @return array
	 */
	public function add_cf7_data_source_events( $events ) {
		$forms     = $this->get_cf7_forms();
		$cf7_events = [];

		foreach ( $forms as $form ) {
			$hook_name  = 'wpcf7_submit_' . $form->ID;
			$fields     = $this->get_form_fields( $form->ID );

			$cf7_events[ $hook_name ] = array_merge(
				$this->common_submission_fields(),
				$fields
			);
		}

		$cf7_events = apply_filters( 'swise_cf7_data_source_events', $cf7_events );

		return array_merge( $events, $cf7_events );
	}

	/**
	 * Handle CF7 form submission after mail is sent
	 *
	 * @since 2.0.0
	 *
	 * @param \WPCF7_ContactForm $contact_form
	 *
	 * @return void
	 */
	public function handle_cf7_submission( $contact_form ) {
		$form_id = $contact_form->id();
		$hook    = 'wpcf7_submit_' . $form_id;

		$all_event_codes = swise_get_data_source_events();

		if ( ! array_key_exists( $hook, $all_event_codes ) ) {
			return;
		}

		$submission = \WPCF7_Submission::get_instance();

		if ( ! $submission ) {
			return;
		}

		$posted_data    = $submission->get_posted_data();
		$uploaded_files = $submission->uploaded_files();

		// Build values array matching the registered event keys
		$values = [
			'form_title'      => $contact_form->title(),
			'submission_date'  => current_time( 'mysql' ),
			'submitter_ip'    => $this->get_submitter_ip( $submission ),
		];

		// Add form field values
		$form_fields = $this->get_form_fields( $form_id );

		foreach ( array_keys( $form_fields ) as $field_key ) {
			// Skip common fields already added above
			if ( isset( $values[ $field_key ] ) ) {
				continue;
			}

			if ( isset( $uploaded_files[ $field_key ] ) ) {
				// Handle file upload — copy to permanent location
				$file_paths = (array) $uploaded_files[ $field_key ];
				$urls       = [];

				foreach ( $file_paths as $file_path ) {
					$permanent_url = $this->handle_file_upload( $file_path );

					if ( $permanent_url ) {
						$urls[] = $permanent_url;
					}
				}

				$values[ $field_key ] = implode( ', ', $urls );
			} elseif ( isset( $posted_data[ $field_key ] ) ) {
				$value = $posted_data[ $field_key ];

				// Arrays (checkboxes, multi-selects) joined with comma
				if ( is_array( $value ) ) {
					$value = implode( ', ', $value );
				}

				$values[ $field_key ] = sanitize_text_field( $value );
			} else {
				$values[ $field_key ] = '';
			}
		}

		$creation_hook = 'sheetwise_scheduled_' . $hook;

		as_enqueue_async_action(
			$creation_hook,
			[
				'args' => [
					'type'   => 'cf7',
					'hook'   => $hook,
					'values' => $values,
					'id'     => $form_id,
				],
			],
			'swise_cf7',
			true
		);
	}

	/**
	 * Get all published CF7 forms
	 *
	 * @since 2.0.0
	 *
	 * @return \WP_Post[]
	 */
	public function get_cf7_forms() {
		if ( $this->forms_cache !== null ) {
			return $this->forms_cache;
		}

		$this->forms_cache = get_posts( [
			'post_type'      => 'wpcf7_contact_form',
			'posts_per_page' => -1,
			'post_status'    => 'publish',
			'orderby'        => 'title',
			'order'          => 'ASC',
		] );

		return $this->forms_cache;
	}

	/**
	 * Extract form fields from a CF7 form using its form tags
	 *
	 * @since 2.0.0
	 *
	 * @param int $form_id CF7 form post ID
	 *
	 * @return array Keyed array of field definitions with label and type
	 */
	public function get_form_fields( $form_id ) {
		$contact_form = \WPCF7_ContactForm::get_instance( $form_id );

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

		$tags   = $contact_form->scan_form_tags();
		$fields = [];

		// CF7 base types that represent user-input fields
		$supported_types = [
			'text', 'email', 'url', 'tel', 'textarea',
			'select', 'checkbox', 'radio', 'file',
			'date', 'number', 'range', 'acceptance',
		];

		foreach ( $tags as $tag ) {
			$basetype = $tag->basetype;

			if ( ! in_array( $basetype, $supported_types, true ) ) {
				continue;
			}

			$name = $tag->name;

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

			$fields[ $name ] = [
				'label' => $this->format_field_label( $name ),
				'type'  => $this->map_cf7_type( $basetype ),
			];
		}

		return $fields;
	}

	/**
	 * Common fields included with every CF7 submission
	 *
	 * @since 2.0.0
	 *
	 * @return array
	 */
	private function common_submission_fields() {
		return [
			'form_title'      => [
				'label' => __( 'Form Title', 'sheet-wise' ),
				'type'  => 'text',
			],
			'submission_date' => [
				'label' => __( 'Submission Date', 'sheet-wise' ),
				'type'  => 'date',
			],
			'submitter_ip'    => [
				'label' => __( 'Submitter IP', 'sheet-wise' ),
				'type'  => 'text',
			],
		];
	}

	/**
	 * Copy an uploaded file to a permanent location and return its URL
	 *
	 * CF7 deletes uploaded files from its temp directory after mail is sent,
	 * so we must copy them before the Action Scheduler processes the sync.
	 *
	 * @since 2.0.0
	 *
	 * @param string $tmp_path Temporary file path from CF7
	 *
	 * @return string|null Permanent URL or null on failure
	 */
	private function handle_file_upload( $tmp_path ) {
		if ( ! file_exists( $tmp_path ) ) {
			return null;
		}

		$upload_dir = wp_upload_dir();
		$target_dir = $upload_dir['basedir'] . '/sheet-wise-cf7/' . gmdate( 'Y' ) . '/' . gmdate( 'm' );

		if ( ! wp_mkdir_p( $target_dir ) ) {
			return null;
		}

		$filename = wp_unique_filename( $target_dir, basename( $tmp_path ) );
		$target   = $target_dir . '/' . $filename;

		if ( ! copy( $tmp_path, $target ) ) {
			return null;
		}

		$target_url = $upload_dir['baseurl'] . '/sheet-wise-cf7/' . gmdate( 'Y' ) . '/' . gmdate( 'm' ) . '/' . $filename;

		return $target_url;
	}

	/**
	 * Get the submitter's IP address from the CF7 submission
	 *
	 * @since 2.0.0
	 *
	 * @param \WPCF7_Submission $submission
	 *
	 * @return string
	 */
	private function get_submitter_ip( $submission ) {
		$meta = $submission->get_meta();

		return isset( $meta['remote_ip'] ) ? sanitize_text_field( $meta['remote_ip'] ) : '';
	}

	/**
	 * Format a CF7 field name into a human-readable label
	 *
	 * Converts "your-name" or "your_email" into "Your Name" or "Your Email"
	 *
	 * @since 2.0.0
	 *
	 * @param string $name CF7 field name
	 *
	 * @return string
	 */
	private function format_field_label( $name ) {
		$label = str_replace( [ '-', '_' ], ' ', $name );

		return ucwords( $label );
	}

	/**
	 * Map CF7 field basetype to a Sheet Wise field type
	 *
	 * @since 2.0.0
	 *
	 * @param string $cf7_type CF7 basetype
	 *
	 * @return string
	 */
	private function map_cf7_type( $cf7_type ) {
		$type_map = [
			'email'    => 'email',
			'url'      => 'url',
			'tel'      => 'tel',
			'number'   => 'number',
			'range'    => 'number',
			'date'     => 'date',
			'file'     => 'file',
			'textarea' => 'text',
		];

		return isset( $type_map[ $cf7_type ] ) ? $type_map[ $cf7_type ] : 'text';
	}

	/**
	 * Clear the cached CF7 forms list
	 *
	 * @since 2.0.0
	 *
	 * @return void
	 */
	public function clear_forms_cache() {
		$this->forms_cache = null;
	}
}
