<?php
/**
 * FluentCRM Add Contact Action
 *
 * Handles adding/updating contacts in FluentCRM through SureForms.
 *
 * @package SureForms
 * @since 1.13.0
 */

namespace SRFM_Pro\Inc\Pro\Native_Integrations\Integrations\FluentCRM\Actions;

use SRFM_Pro\Inc\Pro\Native_Integrations\Integrations\FluentCRM\FluentCRM_Integration;
use SRFM_Pro\Inc\Pro\Native_Integrations\WordPress_Action;
use SRFM_Pro\Inc\Traits\Get_Instance;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * Add Contact Action Class
 *
 * @since 1.13.0
 */
class Add_Contact extends WordPress_Action {
	use Get_Instance;

	/**
	 * Integration name
	 *
	 * @var string
	 * @since 1.13.0
	 */
	protected $integration = 'fluentcrm';

	/**
	 * Action name
	 *
	 * @var string
	 * @since 1.13.0
	 */
	protected $action = 'add_contact';

	/**
	 * Execute the add contact action
	 *
	 * @param array $data Form submission data.
	 * @return array Action result.
	 * @throws \Exception If contact creation fails.
	 * @since 1.13.0
	 */
	protected function execute( $data ) {
		try {
			// Validate required functions.
			if ( ! function_exists( 'FluentCrmApi' ) ) {
				throw new \Exception( 'FluentCRM API functions not found.' );
			}

			// Validate email.
			$email = $data['email'] ?? '';
			if ( empty( $email ) || ! is_email( $email ) ) {
				throw new \Exception( 'Valid email address is required.' );
			}

			$contact_api = FluentCrmApi( 'contacts' );
			$contact     = $contact_api->getContact( trim( $email ) );

			$forced_update = ! is_null( $contact );

			// Prepare contact data.
			$contact_data = [
				'email'          => trim( $email ),
				'first_name'     => $data['first_name'] ?? '',
				'last_name'      => $data['last_name'] ?? '',
				'phone'          => $data['phone'] ?? '',
				'address_line_1' => $data['address_line_1'] ?? '',
				'address_line_2' => $data['address_line_2'] ?? '',
				'city'           => $data['city'] ?? '',
				'state'          => $data['state'] ?? '',
				'postal_code'    => $data['postal_code'] ?? '',
				'country'        => $data['country'] ?? '',
				'prefix'         => $data['prefix'] ?? '',
			];

			// Handle date of birth.
			if ( ! empty( $data['date_of_birth'] ) ) {
				$date_of_birth = \DateTime::createFromFormat( 'Y-m-d', $data['date_of_birth'] );
				if ( ! $date_of_birth ) {
					throw new \Exception( 'Date of birth must be in YYYY-MM-DD format.' );
				}
				$contact_data['date_of_birth'] = $data['date_of_birth'];
			}

			// Handle contact status.
			if ( ! empty( $data['status'] ) ) {
				$valid_statuses = [ 'subscribed', 'unsubscribed', 'pending', 'bounced', 'complained' ];
				if ( in_array( $data['status'], $valid_statuses, true ) ) {
					$contact_data['status'] = $data['status'];
				}
			}

			// Handle custom fields.
			$custom_fields = FluentCRM_Integration::extract_custom_fields( $data );
			if ( ! empty( $custom_fields ) ) {
				$contact_data = array_merge( $contact_data, $custom_fields );
			}

			// Create or update contact.
			$contact = $contact_api->createOrUpdate( $contact_data, $forced_update );

			if ( ! $contact ) {
				throw new \Exception( 'Failed to create or update contact.' );
			}

			// Send double opt-in email if contact is pending.
			if ( 'pending' === $contact->status ) {
				$contact->sendDoubleOptinEmail();
			}

			// Handle tags.
			$tag_ids   = [];
			$tag_names = [];
			if ( ! empty( $data['tag_ids'] ) ) {
				$tag_ids = $this->process_tags_with_creation( $data['tag_ids'], $tag_names );
				if ( ! empty( $tag_ids ) ) {
					$contact->attachTags( $tag_ids );
				}
			}

			// Handle lists.
			$list_ids   = [];
			$list_names = [];
			if ( ! empty( $data['list_ids'] ) ) {
				$list_ids = FluentCRM_Integration::process_lists( $data['list_ids'], $list_names );
				if ( ! empty( $list_ids ) ) {
					$contact->attachLists( $list_ids );
				}
			}

			// Prepare return data.
			$custom_data = $contact->custom_fields() ?? [];

			$return_data = [
				'contact_id'     => $contact->id,
				'full_name'      => $contact->full_name,
				'first_name'     => $contact->first_name,
				'last_name'      => $contact->last_name,
				'email'          => $contact->email,
				'phone'          => $contact->phone,
				'address_line_1' => $contact->address_line_1,
				'address_line_2' => $contact->address_line_2,
				'city'           => $contact->city,
				'state'          => $contact->state,
				'postal_code'    => $contact->postal_code,
				'country'        => $contact->country,
				'status'         => $contact->status,
				'date_of_birth'  => $contact->date_of_birth,
				'prefix'         => $contact->prefix,
				'contact_type'   => $contact->contact_type,
				'source'         => $contact->source,
				'tag_names'      => implode( ', ', $tag_names ),
				'list_names'     => implode( ', ', $list_names ),
			];

			// Add custom fields to return data.
			if ( ! empty( $custom_data ) ) {
				foreach ( $custom_data as $key => $field ) {
					if ( is_array( $field ) ) {
						$return_data[ $key ] = implode( ', ', $field );
					} else {
						$return_data[ $key ] = $field;
					}
				}
			}

			return [
				'success' => true,
				'message' => __( 'Contact added/updated successfully.', 'sureforms-pro' ),
				'data'    => $return_data,
			];

		} catch ( \Exception $e ) {
			return [
				'success' => false,
				'message' => sprintf(
					// translators: %s: Error message.
					__( 'Failed to add/update contact: %s', 'sureforms-pro' ),
					$e->getMessage()
				),
			];
		}
	}

	/**
	 * Check if FluentCRM plugin is active
	 *
	 * @return bool True if FluentCRM is active, false otherwise.
	 * @since 1.13.0
	 */
	protected function is_plugin_active() {
		return defined( 'FLUENTCRM' );
	}

	/**
	 * Process tags and return tag IDs (with tag creation for Add Contact)
	 *
	 * @param mixed $tags Tags data from form.
	 * @param array $tag_names Reference to store tag names.
	 * @return array Array of tag IDs.
	 * @throws \Exception If tag processing fails.
	 * @since 1.13.0
	 */
	private function process_tags_with_creation( $tags, &$tag_names ) {
		// Use shared processing logic first.
		$tag_ids = FluentCRM_Integration::process_tags( $tags, $tag_names );

		// Handle tag creation for string-based tag names (Add Contact specific).
		if ( is_string( $tags ) ) {
			$tags_arr = array_filter( array_map( 'trim', explode( ',', $tags ) ) );

			foreach ( $tags_arr as $tag ) {
				if ( ! is_numeric( $tag ) ) {
					// It's a tag name - find or create.
					if ( ! class_exists( 'FluentCrm\App\Models\Tag' ) ) {
						throw new \Exception( 'FluentCRM Tag model not found.' );
					}

					$existing_tag = \FluentCrm\App\Models\Tag::where( 'title', $tag )->orWhere( 'slug', sanitize_title( $tag ) )->first();

					if ( ! $existing_tag ) {
						// Create new tag.
						$new_tag     = \FluentCrm\App\Models\Tag::create(
							[
								'title' => $tag,
								'slug'  => sanitize_title( $tag ),
							]
						);
						$tag_ids[]   = $new_tag->id;
						$tag_names[] = esc_html( $new_tag->title );
					}
				}
			}
		}

		return array_unique( array_filter( $tag_ids ) );
	}
}

// Initialize the class.
Add_Contact::get_instance();
