<?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 Joomla\CMS\Application\CMSApplicationInterface;
use Joomla\CMS\Factory;
use Joomla\CMS\MVC\Model\ListModel;
use Joomla\Database\DatabaseDriver;
use Joomla\Database\DatabaseQuery;
use RuntimeException;

/**
 * Methods supporting a list of formea records.
 *
 * @since  1.0
 */
class CoreextensionsModel extends ListModel
{
  /**
   * @var CMSApplicationInterface|null
   * @since 1.0.0
   */
  protected $app;

  /**
   * Constructor.
   *
   * @param   array  $config  An optional associative array of configuration settings.
   *
   * @see     \JControllerLegacy
   * @since   1.0
   */
  public function __construct($config = [])
  {
    if (empty($config['filter_fields'])) {
      $config['filter_fields'] = [
        'id',
        'a.id',
        'name',
        'a.name',
        'title',
        'a.title',
        'author',
        'a.author',
        'creation_date',
        'a.creation_date',
        'copyright',
        'a.copyright',
        'license',
        'a.license',
        'author_email',
        'a.author_email',
        'author_url',
        'a.author_url',
        'version',
        'a.version',
        'extension_type',
        'a.extension_type',
        'description',
        'a.description',
        'params',
        'a.params',
        'state',
        'a.state',
      ];
    }

    parent::__construct($config);
    $this->app = Factory::getApplication();
  }

  /**
   * Method to get a DatabaseQuery object for retrieving the data set from a database.
   *
   * @return  DatabaseQuery  A DatabaseQuery object to retrieve the data set.
   *
   * @since   1.6
   */
  protected function getListQuery()
  {
    $columns = [
      'a.id',
      'a.name',
      'a.title',
      'a.author',
      'a.creation_date',
      'a.copyright',
      'a.license',
      'a.author_email',
      'a.author_url',
      'a.version',
      'a.description',
      'a.params',
      'a.state',
      'a.extension_type',
      'a.created_by',
      'a.checked_out',
      'a.publish_up',
      'a.publish_down',
      'a.checked_out_time',
    ];
    // 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',
            implode(', ', $columns)
          )
        )
      )
    );

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

    // 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 published state
    $published = (string) $this->getState('filter.published');

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


    // 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 . ')'
        );
      }
    }


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

    $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.id', $direction = 'desc')
  {
    $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 getItems()
  {
    // Get a storage key.
    $store = $this->getStoreId();

    // Try to load the data from internal storage.
    if (isset($this->cache[$store])) {
      return $this->cache[$store];
    }

    try {
      // Load the list items and add the items to the internal cache.
      $items = $this->_getList($this->_getListQuery(), $this->getStart(), $this->getState('list.limit'));
      if (!empty($items)) {
        $totalItems = count($items);
        for ($i = 0; $i < $totalItems; $i++) {
          $items[$i]->dependable_forms = [];
          $dependableElements          = $this->__getDependableForms($items[$i]->name);
          if (!empty($dependableElements)) {
            $items[$i]->dependable_forms = $dependableElements;
          }
        }
      }
      $this->cache[$store] = $items;
    } catch (RuntimeException $e) {
      $this->app->enqueueMessage($e->getMessage(), 'error');

      return false;
    }

    return $this->cache[$store];
  }

  private function __getDependableForms($validationName)
  {
    /** @var DatabaseDriver $db */
    $db    = $this->getDatabase();
    $query = $db->getQuery(true);
    $query->select(['a.element_id', 'b.title AS element_title']);
    $query->from($db->quoteName('#__formea_element_validations', 'a'))->innerJoin(
      $db->quoteName('#__formea_elements', 'b') . ' ON ' . $db->quoteName('a.element_id') . ' = ' .
        $db->quoteName('b.id')
    );
    $query->where($db->quoteName('a.validation_type') . ' = ' . $db->quote($validationName));
    $db->setQuery($query);

    return $db->loadObjectList();
  }
}
