<?php
namespace SabaiApps\Directories\Component\System\Controller\Admin;

use SabaiApps\Directories\Component\Form;
use SabaiApps\Directories\Context;

/**
 * AbstractSettings provides a base controller for admin settings forms.
 * Handles AJAX submission, tab management, and saving component configuration.
 */
abstract class AbstractSettings extends Form\Controller {

	/**
	 * Executes the controller logic for displaying and processing the settings form.
	 *
	 * @param Context $context
	 */
	protected function _doExecute( Context $context ) {
		$this->_cancelUrl = null;
		if ( $context->getContainer() !== '#drts-content' ) {
			$this->_ajaxSubmit            = true;
			$this->_ajaxOnSuccessRedirect = $this->_ajaxOnErrorRedirect = false;
		}
		parent::_doExecute( $context );
		if ( $context->isSuccess() ) {
			$context->setSuccess( $this->_getSuccessUrl( $context ) );
		}
	}

	/**
	 * Gets the form settings for the settings form, including tab handling.
	 *
	 * @param Context $context
	 * @param array   $storage
	 * @return array
	 */
	final protected function _doGetFormSettings( Context $context, array &$storage ) {
		$this->getPlatform()->loadJqueryUiJs( array( 'effects-highlight' ) );

		$form = $this->_getSettingsForm( $context, $storage );
		if ( empty( $this->_submitButtons ) ) {
			$this->_submitButtons[] = array(
				'#btn_label' => __( 'Save Changes', 'directories-pro' ),
				'#btn_color' => 'primary',
				'#btn_size'  => 'lg',
			);
		}

		if ( ! empty( $form['#tabs'] ) ) {
			// Show tab requested if any
			if ( $tab = $context->getRequest()->asStr( '_drts_form_current_tab' ) ) {
				if ( isset( $form['#tabs'][ $tab ] ) ) {
					$form['#tabs'][ $tab ]['#active'] = true;
				}
			} else {
				foreach ( array_keys( $form['#tabs'] ) as $tab_name ) {
					if ( ! empty( $form['#tabs'][ $tab ]['#active'] ) ) {
						$tab = $tab_name;
					}
				}
			}
			// Save current tab name as hidden value
			$form['#js_ready'][]            = sprintf(
				'$(\'#__FORM_ID__ > .%1$snav > .drts-content-tab\').on(\'shown.bs.tab\', function (event) {
    $(\'#__FORM_ID__\').find(\'input.drts-form-current-tab\').val(event.target.getAttribute(\'data-tab-name\'));
    $(\'#__FORM_ID__\').find(\'button[type="submit"]\').toggle($(this).data("no-submit") !== 1);
    if ($(this).data("submit-btn-label")) {
        $(\'#__FORM_ID__\').find(\'button[type="submit"]\').text($(this).data("submit-btn-label"));
    }
});
var activeTab = $(\'#__FORM_ID__ > .%1$snav > .%1$sactive\');
if (activeTab.data("no-submit") === 1) {
    $(\'#__FORM_ID__\').find(\'button[type="submit"]\').hide();
} else {
    if (activeTab.data("submit-btn-label")) {
        $(\'#__FORM_ID__\').find(\'button[type="submit"]\').text(activeTab.data("submit-btn-label"));
    }
}',
				DRTS_BS_PREFIX
			);
			$form['_drts_form_current_tab'] = array(
				'#class'         => 'drts-form-current-tab',
				'#type'          => 'hidden',
				'#default_value' => empty( $tab ) ? null : $tab,
			);
		}

		return $form;
	}

	/**
	 * Returns the settings form array for the controller.
	 *
	 * @param Context $context
	 * @param array   $formStorage
	 * @return array
	 */
	abstract protected function _getSettingsForm( Context $context, array &$formStorage );

	/**
	 * Gets the URL to redirect to after successful form submission.
	 *
	 * @param Context $context
	 * @return string
	 */
	protected function _getSuccessUrl( Context $context ) {
		if ( $context->getContainer() !== '#drts-content' ) {
			return ''; // return empty for no redirection URL
		}

		return $this->Url( $context->getRoute(), $this->_getSuccessUrlParams( $context ) );
	}

	/**
	 * Gets additional URL parameters for the success redirect.
	 *
	 * @param Context $context
	 * @return array
	 */
	protected function _getSuccessUrlParams( Context $context ) {
		$params = array();
		// Pass current selected tab if any
		if ( $tab = $context->getRequest()->asStr( '_drts_form_current_tab' ) ) {
			$params['_drts_form_current_tab'] = $tab;
		}
		return $params;
	}

	/**
	 * Handles form submission, saves config, and clears cache.
	 *
	 * @param Form\Form $form
	 * @param Context   $context
	 */
	public function submitForm( Form\Form $form, Context $context ) {
		unset( $form->values[ Form\FormComponent::FORM_SUBMIT_BUTTON_NAME ] );
		$this->_saveConfig( $context, $form->values, $form );
		$this->clearComponentInfoCache();
		if ( ! isset( $this->_successFlash ) ) {
			$this->_successFlash = __( 'Settings saved.', 'directories-pro' );
		}
	}

	/**
	 * Saves the configuration for the component(s).
	 *
	 * @param Context   $context
	 * @param array     $config
	 * @param Form\Form $form
	 */
	protected function _saveConfig( Context $context, array $config, Form\Form $form ) {
		$overwrite_configs = array();
		$component_configs = $this->_getComponentConfigs( $context, $config, $form, $overwrite_configs );
		foreach ( array_keys( $component_configs ) as $component_name ) {
			$this->System_Component_saveConfig( $component_name, $component_configs[ $component_name ], empty( $overwrite_configs[ $component_name ] ) );
		}
	}

	/**
	 * Extracts component-specific configuration from the form.
	 *
	 * @param Context   $context
	 * @param array     $config
	 * @param Form\Form $form
	 * @param array     &$overwriteConfigs
	 * @return array
	 */
	protected function _getComponentConfigs( Context $context, array $config, Form\Form $form, array &$overwriteConfigs = array() ) {
		$component_configs = array();
		$form_settings     = $this->_getComponentConfigFormSettings( $form );
		foreach ( array_keys( $form_settings ) as $key ) {
			if ( isset( $form_settings[ $key ] )
				&& is_array( $form_settings[ $key ] )
				&& isset( $form_settings[ $key ]['#component'] )
				&& isset( $config[ $key ] )
			) {
				$component_name = $form_settings[ $key ]['#component'];
				if ( ! isset( $component_configs[ $component_name ] ) ) {
					$component_configs[ $component_name ] = array();
				}
				// Exclude certain configs?
				if ( ! empty( $form_settings[ $key ]['#component_config_exclude'] ) ) {
					$config[ $key ] = array_diff_key( $config[ $key ], array_flip( $form_settings[ $key ]['#component_config_exclude'] ) );
				} elseif ( ! empty( $form_settings[ $key ]['#component_config_overwrite'] ) ) {
					$overwriteConfigs[ $component_name ] = true;
				}
				$component_configs[ $component_name ] += $config[ $key ];
			}
		}

		return $component_configs;
	}

	/*
	 * Returns the form settings array for component configuration.
	 *
	 * @param Form\Form $form
	 * @return array
	 */
	protected function _getComponentConfigFormSettings( Form\Form $form ) {
		return $form->settings;
	}
}
