<?php

/**
 * @package     Joomla.Administrator
 * @subpackage  com_formea
 *
 * @copyright   Copyright (C) 2010-2025 Feseur Sdn Bhd. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 * @version     1.3.0
 */

namespace Joomla\Component\Formea\Administrator\Model;

defined('_JEXEC') or die;

use Exception;
use Feseur\Library\FsrDate;
use Feseur\Library\FsrHelper;
use Joomla\CMS\Date\Date;
use Joomla\CMS\Factory;
use Joomla\CMS\Form\Form;
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\Model\AdminModel;
use Joomla\CMS\Object\CMSObject;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\Component\Formea\Site\Libraries\FormeaValidation;
use Joomla\Database\DatabaseDriver;
use Joomla\Registry\Registry;
use Joomla\Utilities\ArrayHelper;

/**
 * Item Model for a Formea.
 *
 * @since  1.0.0
 */
class ValidationModel extends AdminModel
{
	/**
	 * The type alias for this content type.
	 *
	 * @var    string
	 * @since  1.0.0
	 */
	public $typeAlias = 'com_formea.validation';


	/**
	 * Method to get the row form.
	 *
	 * @param   array    $data      Data for the form.
	 * @param   boolean  $loadData  True if the form is to load its own data (default case), false if not.
	 *
	 * @return  Form|boolean  A \Form object on success, false on failure
	 *
	 * @throws  Exception
	 * @since   1.0.0
	 */
	public function getForm($data = array(), $loadData = true)
	{
		if (empty($data)) {
			$data = $this->getItem();
		} else {
			$data = (object) $data;
		}

		$configField = '';
		if (isset($data->name)) {
			$filePathXml = JPATH_ROOT . '/components/com_formea/plugins/validation/' . $data->name . '/' . $data->name . '.xml';
			$root        = simplexml_load_file($filePathXml);
			$configField = $root->config->children()->asXML();
		}

		$xml = file_get_contents(JPATH_ADMINISTRATOR . '/components/com_formea/forms/validation.xml');

		if (!empty($configField)) {
			$xml = str_replace('<fields name="params"/>', $configField, $xml);
		}

		// Get the form.
		$form = $this->loadForm(
			'com_formea.validation',
			$xml,
			['control' => 'jform', 'load_data' => $loadData]
		);

		if (empty($form)) {
			return false;
		}

		return $form;
	}

	protected function _addLangFields($lang_code)
	{
		$lang_code = str_replace('-', '_', $lang_code);
		$con       = '    <fields name="' . $lang_code . '">' . "\r\n";
		$con       .= '      <field name="form_heading"  label="Form Heading" type="text"/>' . "\r\n";
		$con       .= '    </fields>' . "\r\n";

		return $con;
	}

	/**
	 * Method to get the data that should be injected in the form.
	 *
	 * @return  mixed  The data for the form.
	 *
	 * @throws  Exception
	 * @since   1.0.0
	 */
	protected function loadFormData()
	{

		$data = $this->getItem();

		$this->preprocessData('com_formea.formea', $data);

		return $data;
	}

	/**
	 * Method to get a single record.
	 *
	 * @param   integer  $pk  The id of the primary key.
	 *
	 * @return  mixed  Object on success, false on failure.
	 *
	 * @throws  Exception
	 * @since   1.0.0
	 */
	public function getItem($pk = null)

	{
		$pk    = (!empty($pk)) ? $pk : (int) $this->getState($this->getName() . '.id');
		$table = $this->getTable();

		if ($pk > 0) {
			// Attempt to load the row.
			$return = $table->load($pk);

			// Check for a table object error.
			if ($return === false) {
				// If there was no underlying error, then the false means there simply was not a row in the db for this $pk.
				if (!$table->getError()) {
					$this->setError(Text::_('JLIB_APPLICATION_ERROR_NOT_EXIST'));
				} else {
					$this->setError($table->getError());
				}

				return false;
			}
		}

		// Convert to the CMSObject before adding other data.
		$properties  = $table->getProperties(1);
		$detailArray = [];
		if (isset($properties['id'])) {
			if ($properties['id'] > 0) {
				$container = Factory::getContainer();
				/** @var DatabaseDriver $db */
				$db = $container->get('DatabaseDriver');
				$query = $db->getQuery(true);
				$query->select('*');
				$query->from($db->quoteName('#__formea_formdetails'));
				$query->where($db->quoteName('form_id') . ' = ' . $properties['id']);
				$db->setQuery($query);
				$details = $db->loadObjectList();
				if (!empty($details)) {
					$totalDetails = count($details);
					for ($i = 0; $i < $totalDetails; $i++) {
						$lTag               = str_replace('-', '_', $details[$i]->language);
						$detailArray[$lTag] = [
							'form_heading' => $details[$i]->form_heading
						];
					}
				}
			}
		}
		$properties['details'] = $detailArray;

		$item = ArrayHelper::toObject($properties, CMSObject::class);

		if (property_exists($item, 'params')) {
			$registry     = new Registry($item->params);
			$item->params = $registry->toArray();
		}

		return $item;
	}

	/**
	 * Preprocess the form.
	 *
	 * @param   Form    $form   Form object.
	 * @param   object  $data   Data object.
	 * @param   string  $group  Group name.
	 *
	 * @return  void
	 *
	 * @throws  Exception
	 * @since   1.0.0
	 */
	protected function preprocessForm(Form $form, $data, $group = 'content')
	{
		parent::preprocessForm($form, $data, $group);
	}

	/**
	 * Method to save the form data.
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return boolean  True on success, False on error.
	 *
	 * @throws Exception
	 * @since 1.0.0
	 */
	public function save($data)
	{
		// var_dump($data);die;
		$app         = Factory::getApplication();
		$user        = $app->getIdentity();
		$isNew       = false;
		$currentDate = new Date();
		if ((int) $data['id'] === 0) {
			$data['created_date']  = $currentDate->toSql();
			$data['created_by']    = $user->id;
			$data['modified_date'] = $currentDate->toSql();
			$data['modified_by']   = $user->id;
			$isNew                 = true;
		} else {
			$data['modified_date'] = $currentDate->toSql();
			$data['modified_by']   = $user->id;
		}
		$saved   = parent::save($data);
		$form_id = $this->getState($this->getName() . '.id');

		return $saved;
	}

	/**
	 * Install a validation plugin from given package
	 *
	 * @param $plugin
	 *
	 * @return bool
	 * @throws Exception
	 * @since 1.0.0
	 */
	public function install($plugin)
	{
		$db = $this->getDatabase();

		if (!isset($plugin['name'])) {
			throw new Exception(Text::_('COM_FORMEA_FILE_NOT_FOUND'));
		}
		if (!isset($plugin['type']) || !in_array($plugin['type'], FsrHelper::commonZipMimeType())) {
			throw new Exception(Text::_('COM_FORMEA_INVALID_FILE_TYPE'));
		}

		if ($plugin['error'] || $plugin['size'] < 1) {
			throw new Exception(Text::_('COM_FORMEA_UPLOAD_PLUGIN_ERROR'));
		}
		$pluginGroup = 'validation';

		$destinationPath = FORMEA_PLG_PATH . '/';
		$uploadPlugin    = FsrHelper::uploadFsrComPlugin($plugin, 'COM_FORMEA', 'formeaplugin', $destinationPath, $pluginGroup, 'com_formea');
		if (!$uploadPlugin->success) {
			$msg = Text::_('COM_FORMEA_UPLOAD_PLUGIN_FAILED');
			if (isset($uploadPlugin->msg[0])) {
				$msg = $uploadPlugin->msg[0]->text;
			}
			throw new Exception($msg);
		}

		$result = $uploadPlugin->result;
		if (!isset($result['group'])) {
			throw new Exception(Text::_('COM_FORMEA_UNKNOWN_PLUGIN_TYPE'));
		}

		if ($result['group'] !== $pluginGroup) {
			throw new Exception(Text::_('COM_FORMEA_ELTYPE_INVALID_PLUGIN'));
		}
		$tableName  = '#__formea_validations';
		$name       = $result['name'];
		$plgVersion = $result['version'];

		$currentDate = new FsrDate();
		$app         = Factory::getApplication();
		$currentUser = $app->getIdentity();

		/** @var DatabaseDriver $db */
		$db    = $this->getDatabase();
		$query = $db->getQuery(true);
		$query->select('id')
			->from($tableName)
			->where('name = "' . $name . '"');
		$db->setQuery($query);
		$pluginId = (int) $db->loadResult();

		$obj = [
			'name'          => $name,
			'title'         => $result['title'],
			'author'        => $result['author'],
			'creation_date' => $result['creationDate'],
			'copyright'     => $result['copyright'],
			'license'       => $result['license'],
			'author_email'  => $result['authorEmail'],
			'author_url'    => $result['authorUrl'],
			'version'       => $result['version'],
			'description'   => $result['description'],
			'checked_out'   => 0,
		];
		if ($pluginId > 0) {
			$obj['id']            = $pluginId;
			$obj['modified_date'] = $currentDate->toSql();
			$obj['modified_by']   = $currentUser->get('id');
			$obj                  = (object) $obj;
			$db->updateObject($tableName, $obj, 'id');
			$app->enqueueMessage(Text::sprintf('COM_FORMEA_N_PLUGIN_N_UPDATED', ucwords($pluginGroup), $name . ' v' . $plgVersion));
		} else {
			$obj['created_date'] = $currentDate->toSql();
			$obj['created_by']   = $currentUser->get('id');
			$obj['state']        = 0;
			$obj                 = (object) $obj;
			$db->insertObject($tableName, $obj);
			$app->enqueueMessage(Text::sprintf('COM_FORMEA_S_PLUGIN_S_INSTALLED', ucwords($pluginGroup), $name . ' v' . $plgVersion), 'message');
		}

		return true;
	}

	public function delete(&$pks)
	{

		if (is_array($pks)) {
			$pks = ArrayHelper::toInteger((array) $pks);
			// Include the plugins for the delete events.
			PluginHelper::importPlugin($this->events_map['delete']);
			$table = $this->getTable();

			$totalIds = count($pks);
			for ($i = 0; $i < $totalIds; $i++) {
				if ($table->load($pks[$i])) {
					if ($this->canDelete($table)) {
						$context = $this->option . '.' . $this->name;

						// Trigger the before delete event.
						$result = Factory::getApplication()->triggerEvent($this->event_before_delete, [$context, $table]);

						if (in_array(false, $result, true)) {
							$this->setError($table->getError());

							return false;
						}

						$formeaValidation = new FormeaValidation(['id' => $pks[$i]]);
						$delete           = $formeaValidation->deleteValidationPlugin();
						if (!$delete->success) {
							if (isset($delete->msg[0])) {
								$this->setError($delete->msg[0]->text);
							} else {
								$this->setError(Text::_('COM_FORMEA_FAILED_TO_DELETE_VALIDATION'));
							}

							return false;
						}
						Factory::getApplication()->triggerEvent($this->event_after_delete, [$context, $table]);
					}
				}
			}

			// Clear the component's cache
			$this->cleanCache();
		}

		return true;
	}
}
