<?php

namespace Limb_Chatbot\Includes\Services\Actions;

use Exception;
use Limb_Chatbot\Includes\Data_Objects\Action;
use Limb_Chatbot\Includes\Data_Objects\Action_Plan;
use Limb_Chatbot\Includes\Data_Objects\Action_Submission;
use Limb_Chatbot\Includes\Data_Objects\Chat;
use Limb_Chatbot\Includes\Interfaces\Action_Callback_Interface;
use Limb_Chatbot\Includes\Services\Helper;
use Limb_Chatbot\Includes\Services\User_Manager;

/**
 * Class Action_Submission_Service
 *
 * Handles action submission processing and callback execution.
 *
 * @package Limb_Chatbot\Includes\Services
 * @since 1.0.0
 */
class Action_Submission_Service {

	/**
	 * @var Action_Plan action/action plan
	 */
	private Action_Plan $action_plan;

	/**
	 * @var Action Action instance
	 */
	private Action $action;

	/**
	 * @var Chat|null Chat instance
	 */
	private ?Chat $chat;

	/**
	 * Constructor
	 *
	 * @param  Action  $action  Action instance
	 * @param  Action_Plan  $action_plan  action plan
	 * @param  Chat|null  $chat  Chat instance
	 */
	public function __construct( Action $action, Action_Plan $action_plan, ?Chat $chat = null ) {
		$this->action      = $action;
		$this->action_plan = $action_plan;
		$this->chat        = $chat;
	}

	/**
	 * Process action submission
	 *
	 * @return Action_Submission
	 * @throws Exception
	 */
	public function process_submission(): Action_Submission {
		// Create an action submission instance
		$action_submission = $this->create_action_submission();
		try {
			$chain_executor = new Action_Callback_Chain_Executor( $action_submission );
			// Check for legacy callback filter (backward compatibility)
			$legacy_callback = apply_filters( "lbaic_action_submission_{$this->action->get_name()}", null );

			if ( $legacy_callback instanceof Action_Callback_Interface ) {
				$action_submission = $legacy_callback->execute( $action_submission );
				$this->save_submission( $action_submission );

				// Process lead capture after successful submission
				if ( $action_submission->is_success() ) {
					$this->process_lead_capture( $action_submission );
				}

				return $action_submission;
			}

			// Execute callback chain if callbacks exist
			if ( $callbacks = $this->action->has_callbacks() ) {
				$action_submission = $chain_executor->execute_chain( $callbacks, $this->action_plan );
				$this->save_submission( $action_submission );

				// Process lead capture after successful submission
				if ( $action_submission->is_success() ) {
					$this->process_lead_capture( $action_submission );
				}

				return $action_submission;
			}

			$this->save_submission( $action_submission );

			// Process lead capture after successful submission
			if ( $action_submission->is_success() ) {
				$this->process_lead_capture( $action_submission );
			}

			return $action_submission;
		} catch ( Exception $e ) {
			$error = Helper::get_wp_error( $e );
			$action_submission->mark_as_failed( $error->get_error_message() );
			$this->save_submission( $action_submission );

			return $action_submission;
		}
	}

	/**
	 * Save action submission to database
	 *
	 * @param  Action_Submission  $submission  The submission to save
	 *
	 * @return Action_Submission|null The submission ID or null if save failed
	 * @since 1.0.0
	 */
	private function save_submission( Action_Submission $submission ): ?Action_Submission {
		try {
			return $submission->save();
		} catch ( Exception $e ) {
			Helper::log( $e, __METHOD__ );

			return null;
		}
	}

	/**
	 * Create action submission record
	 *
	 * @return Action_Submission
	 * @throws Exception
	 */
	public function create_action_submission(): Action_Submission {
		$submission = new Action_Submission();
		$submission->set_action_id( $this->action->get_id() );
		$submission->set_action_data( $this->action_plan->collected_fields() );
		$submission->set_chatbot_user_id( User_Manager::instance()->get_current_user()->get_id() );
		if ( $this->chat ) {
			$submission->set_chat_uuid( $this->chat->uuid );
		}
		$submission->set_created_at( current_time( 'mysql', true ) );

		return $submission;
	}

	/**
	 * Process lead capture for the action submission
	 *
	 * Delegates to Lead_Capture_Handler to process any lead capture fields
	 * configured on action parameters.
	 *
	 * @param  Action_Submission  $submission  The successful action submission
	 *
	 * @return void
	 * @since 1.0.0
	 */
	private function process_lead_capture( Action_Submission $submission ): void {
		try {
			$handler = new Lead_Capture_Handler();
			$handler->process_lead_capture( $submission, $this->action_plan, $this->chat );
		} catch ( Exception $e ) {
			Helper::log( $e, __METHOD__ );
		}
	}
}