<?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\Database\DatabaseQuery;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\Model\ListModel;
use Joomla\Database\DatabaseDriver;
use Joomla\Utilities\ArrayHelper;

/**
 * Methods supporting a list of formea records.
 *
 * @since  1.0
 */
class DashboardModel extends ListModel
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @throws Exception
	 * @since   1.0
	 * @see     \JControllerLegacy
	 */
	public function __construct($config = [])
	{
		if (empty($config['filter_fields'])) {
			$config['filter_fields'] = [
				'id',
				'a.id',
				'name',
				'a.name',
				'alias',
				'a.alias',
				'catid',
				'a.catid',
				'category_id',
				'category_title',
				'checked_out',
				'a.checked_out',
				'checked_out_time',
				'a.checked_out_time',
				'published',
				'a.published',
				'access',
				'a.access',
				'access_level',
				'ordering',
				'a.ordering',
				'language',
				'a.language',
				'language_title',
				'publish_up',
				'a.publish_up',
				'publish_down',
				'a.publish_down',
			];
		}

		parent::__construct($config);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return  DatabaseQuery
	 *
	 * @since   1.0
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db    = $this->getDatabase();
		$query = $db->getQuery(true);

		// Select the required fields from the table.
		$query->select(
			$db->quoteName(
				explode(
					', ',
					$this->getState(
						'list.select',
						'a.id, a.name, a.catid' .
							', a.access' .
							', a.checked_out' .
							', a.checked_out_time' .
							', a.language' .
							', a.ordering' .
							', a.state' .
							', a.published' .
							', a.publish_up, a.publish_down'
					)
				)
			)
		);

		$query->from($db->quoteName('#__formeas_details', 'a'));

		// Join over the asset groups.
		$query->select($db->quoteName('ag.title', 'access_level'))
			->join(
				'LEFT',
				$db->quoteName('#__viewlevels', 'ag') . ' ON ' . $db->quoteName('ag.id') . ' = ' . $db->quoteName('a.access')
			);

		// Join over the categories.
		$query->select($db->quoteName('c.title', 'category_title'))
			->join(
				'LEFT',
				$db->quoteName('#__categories', 'c') . ' ON ' . $db->quoteName('c.id') . ' = ' . $db->quoteName('a.catid')
			);

		// Join over the language
		$query->select($db->quoteName('l.title', 'language_title'))
			->select($db->quoteName('l.image', 'language_image'))
			->join(
				'LEFT',
				$db->quoteName('#__languages', 'l') . ' ON ' . $db->quoteName('l.lang_code') . ' = ' . $db->quoteName('a.language')
			);

		// Join over the users for the checked out user.
		$query->select($db->quoteName('uc.name', 'editor'))
			->join(
				'LEFT',
				$db->quoteName('#__users', 'uc') . ' ON ' . $db->quoteName('uc.id') . ' = ' . $db->quoteName('a.checked_out')
			);

		// Filter by access level.
		if ($access = $this->getState('filter.access')) {
			$query->where($db->quoteName('a.access') . ' = ' . (int) $access);
		}

		// Filter by published state
		$published = (string) $this->getState('filter.published');

		if (is_numeric($published)) {
			$query->where($db->quoteName('a.published') . ' = ' . (int) $published);
		} elseif ($published === '') {
			$query->where('(' . $db->quoteName('a.published') . ' = 0 OR ' . $db->quoteName('a.published') . ' = 1)');
		}

		// Filter by a single or group of categories.
		$categoryId = $this->getState('filter.category_id');

		if (is_numeric($categoryId)) {
			$query->where($db->quoteName('a.catid') . ' = ' . (int) $categoryId);
		} elseif (is_array($categoryId)) {
			$query->where($db->quoteName('a.catid') . ' IN (' . implode(',', ArrayHelper::toInteger($categoryId)) . ')');
		}

		// Filter by search in name.
		$search = $this->getState('filter.search');

		if (!empty($search)) {
			if (stripos($search, 'id:') === 0) {
				$query->where('a.id = ' . (int) substr($search, 3));
			} else {
				$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
				$query->where(
					'(' . $db->quoteName('a.name') . ' LIKE ' . $search . ')'
				);
			}
		}

		// Filter on the language.
		if ($language = $this->getState('filter.language')) {
			$query->where($db->quoteName('a.language') . ' = ' . $db->quote($language));
		}

		// Add the list ordering clause.
		$orderCol  = $this->state->get('list.ordering', 'a.name');
		$orderDirn = $this->state->get('list.direction', 'asc');

		if ($orderCol == 'a.ordering' || $orderCol == 'category_title') {
			$orderCol = $db->quoteName('c.title') . ' ' . $orderDirn . ', ' . $db->quoteName('a.ordering');
		}

		$query->order($db->escape($orderCol . ' ' . $orderDirn));

		return $query;
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 *
	 * @param   string  $ordering   An optional ordering field.
	 * @param   string  $direction  An optional direction (asc|desc).
	 *
	 * @return  void
	 *
	 * @since   1.0
	 */
	protected function populateState($ordering = 'a.name', $direction = 'asc')
	{
		$app = Factory::getApplication();

		$forcedLanguage = $app->input->get('forcedLanguage', '', 'cmd');

		// Adjust the context to support modal layouts.
		if ($layout = $app->input->get('layout')) {
			$this->context .= '.' . $layout;
		}

		// Adjust the context to support forced languages.
		if ($forcedLanguage) {
			$this->context .= '.' . $forcedLanguage;
		}

		// List state information.
		parent::populateState($ordering, $direction);

		// Force a language.
		if (!empty($forcedLanguage)) {
			$this->setState('filter.language', $forcedLanguage);
		}
	}

	public function installPlugin($plugin)
	{

		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'));
		}
		$destinationPath = FORMEA_PLG_PATH . DIRECTORY_SEPARATOR;
		$uploadPlugin    = FsrHelper::uploadFsrComPlugin($plugin, 'COM_FORMEA', 'formeaplugin', $destinationPath, null, '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'));
		}
		$pluginGroup = $result['group'];
		$tableName   = null;
		if ($pluginGroup === 'element') {
			$tableName = '#__formea_eltypes';
		} elseif ($pluginGroup === 'validation') {
			$tableName = '#__formea_validations';
		} elseif ($pluginGroup === 'theme') {
			$tableName = '#__formea_themes';
		} elseif ($pluginGroup === 'core') {
			$tableName = '#__formea_cores';
		}


		if (empty($tableName)) {
			throw new Exception(Text::_('COM_FORMEA_UNKNOWN_TABLE'));
		}
		$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 ($pluginGroup === 'element') {
			$value_type = 0;
			if (isset($result['valueType'])) {
				$value_type = $result['valueType'];
			}
			$obj['value_type'] = $value_type;
		}

		if ($pluginGroup === 'core') {
			$hasView = 0;

			if (isset($result['hasView'])) {
				$hasView = (int) $result['hasView'];
			}
			$obj['has_view']       = $hasView;
			$obj['extension_type'] = $result['extensionType'];
		}

		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;
	}
}
