<?php
/*
 * Copyright (c) 2025, Tribal Limited
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Zenario, Tribal Limited nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL TRIBAL LTD BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
if (!defined('NOT_ACCESSED_DIRECTLY')) exit('This file may not be directly accessed');

class zenario_users__organizer__users extends zenario_users {
	
	
	public function preFillOrganizerPanel($path, &$panel, $refinerName, $refinerId, $mode) {
		
		ze\tuix::flagEncryptedColumns($panel, 'u', 'users');
		ze\tuix::flagEncryptedColumns($panel, 'PU', 'users');
		
		if (!$refinerName) {
			$panel['db_items']['where_statement'] = $panel['db_items']['custom_where_statement_if_no_refiner'];
		}
		
		if ($refinerName == 'group_members') {
			$panel['refiners']['group_members']['sql'] = "custom.`". ze\escape::sql(ze\dataset::fieldDBColumn($refinerId)). "` = 1";
		}
		
		if ($refinerName == 'smart_group') {
			ze\smartGroup::sql(
				$panel['refiners']['smart_group']['sql'],
				$panel['refiners']['smart_group']['table_join'],
				$refinerId, $list = true, 'u', 'custom');

		} else {
			unset($panel['columns']['opted_out']);
			unset($panel['columns']['opted_out_on']);
			unset($panel['columns']['opt_out_method']);
		}
		
		if (isset($panel['collection_buttons']['users_dataset'])) {
			$panel['collection_buttons']['users_dataset']['link']['path'] =
				'zenario__administration/panels/custom_datasets/item_buttons/edit_gui//'.
				ze\dataset::details('users', 'id').
				'//';
		}
		
		if (ze::setting('user_use_screen_name')) {
			$convertToContactButtonConfirmationMessage =
				"Are you sure you want to convert the user \"[[identifier]]\" to contact?
                                
            	The user's password and screen name will be cleared and they will no longer be able to log in to a password-protected area of your site.";
		} else {
			$convertToContactButtonConfirmationMessage =
				"Are you sure you want to convert the user \"[[identifier]]\" to contact?
                                
            	The user's password will be cleared and they will no longer be able to log in to a password-protected area of your site.";
		}
		$panel['item_buttons']['convert_to_contact']['ajax']['confirm']['message'] = $convertToContactButtonConfirmationMessage;
	}
	
	//The quickSearchOrganizerPanel() placeholder method adds the ability for
	//panels to add specific logic to their quick-searches, that's not tied to a specific column.
	//This was added for T13107, Searching for users/contacts in Organizer
	public function quickSearchOrganizerPanel($path, &$panel, $refinerName, $refinerId, $mode, $searchString) {
		$sql = '';
		
		//Catch the case where an admin is trying to search for a full name, e.g. "John Smith".
		//As per the task we'll also allow the words in reverse order, e.g. "Smith, John" also should work.
		$searchTerms = ze\ray::explodeAndTrim(preg_replace('@\s@', ',', $searchString));
		
		if (count($searchTerms) == 2) {
			
			$firstNameCol = $panel['columns']['first_name'];
			$lastNameCol = $panel['columns']['name'];
			
			//Note: If either of the first or last name columns are encrypted but not hashed,
			//then we can't do this logic.
			if (!empty($firstNameCol['searchable'])
			 && !empty($lastNameCol['searchable'])) {
				
				$sql .= '
					OR ('. self::writeCheck($firstNameCol, $searchTerms[0]). ' AND '. self::writeCheck($lastNameCol, $searchTerms[1]). ')
					OR ('. self::writeCheck($firstNameCol, $searchTerms[1]). ' AND '. self::writeCheck($lastNameCol, $searchTerms[0]). ')';
			}
		}
		
		return $sql;
	}
	
	private static function writeCheck($col, $searchTerm) {
		if (empty($col['encrypted']['hashed'])) {
			return $col['db_column']. " LIKE '". ze\escape::like($searchTerm). "%'";
		} else {
			return $col['encrypted']['hashed_column']. " = '". ze\escape::hashedColumn($searchTerm). "'";
		}
	}
	
	function getEncryptedColumns($table) {
		$db = ze::$dbL;
		$tableName = $db->prefix. $table;
		
		$cols = [];
	
		if (!isset($db->cols[$tableName])) {
			$db->checkTableDef($tableName);
		}
		
		if (!empty($db->cols[$tableName])) {
			foreach ($db->cols[$tableName] as $col) {
				if ($col->encrypted) {
					$cols[] = $col;
				}
			}
		}
		
		return $cols;
	}
	
	public function fillOrganizerPanel($path, &$panel, $refinerName, $refinerId, $mode) {
		
		//If it looks like a site is supposed to be using encryption, but it's not set up properly,
		//show an error message.
		ze\pdeAdm::showNoticeOnPanelIfConfIsBad($panel);
		
		
		if (!ze\module::isRunning('zenario_extranet')) {
			$panel['collection_buttons']['add']['label'] = ze\admin::phrase('Create a contact');
			unset($panel['item_buttons']['convert_to_user']);
		}
		
		$hasUserTimersRunning = ze\module::inc('zenario_user_timers');
		
		// Add dataset ID to import and export buttons
		$dataset = ze\dataset::details('users');
		$panel['collection_buttons']['import']['admin_box']['key']['dataset'] = 
		$panel['collection_buttons']['export']['admin_box']['key']['dataset'] = 
		$panel['collection_buttons']['donwload_sample_file']['admin_box']['key']['dataset'] = 
			$dataset['id'];
		
		// If no users, hide export button
		if (count($panel['items']) <= 0) {
			$panel['collection_buttons']['export']['hidden'] = true;
		}
		

		//If a filter with parent/child buttons is set, make sure to change the label of the parent to what was chosen.
		if (!empty(zenario_organizer::filterValue('has_logged_in'))) {
			if (zenario_organizer::filterIsNot('has_logged_in')) {
				$panel['quick_filter_buttons']['has_logged_in']['label'] =
					$panel['quick_filter_buttons']['never_logged_in']['label'];
			} else {
				$panel['quick_filter_buttons']['has_logged_in']['label'] =
					$panel['quick_filter_buttons']['logged_in']['label'];
			}
		}
		
		
		//Add user images to each user, if they have an image
		foreach ($panel['items'] as $id => &$item) {
			$item['traits'] = [];
				
			if (!empty($item['checksum'])) {
				$item['traits']['has_image'] = true;
				$img = '&usage=user&c='. $item['checksum'];
	
				$item['image'] = 'zenario/file.php?og=1'. $img;
			}
			
			if ($item['status'] == 'contact') {
				$item['traits']['is_contact'] = true;
			} elseif ($item['status'] == 'active'){
				$item['traits']['active'] = true;
			} else {
				$item['traits']['suspended'] = true;
			}
			
			if ($item['status'] == 'contact') {
				$item['row_class'] = 'contact';
			} elseif ($item['status'] == 'pending') {
				$item['row_class'] = 'user_pending';
			} elseif ($item['status'] == 'active') {
				if ($hasUserTimersRunning) {
					$timerStatus = ze\row::get(ZENARIO_USER_TIMERS_PREFIX.'user_timer_link', 'status', $item['id']);
					if ($timerStatus == 'active') {
						$item['row_class'] = 'user_active_timer';
					} else {
						$item['row_class'] = 'user_active';
					}
				} else {
					$item['row_class'] = 'user_active';
				}
			}
			
			if ($item['status'] == 'contact') {
				$item['user_type'] = 'contact';
			} else {
				$item['user_type'] = 'user';
			}
			
			// Get a users groups
			$groups = ze\user::groups($id, true, true);
			$item['groups'] = implode(', ', $groups);
			
			//$firstGroupMessage = '';
			//$counter = 0;
			//foreach ($groups as $id => &$value) {
			//	$value = $groupNames[$id];
			//	if (++$counter == 1) {
			//		$firstGroupMessage .= $value;
			//	}
			//}
			//if ($firstGroupMessage && count($groups) > 1) {
			//	$firstGroupMessage .= ' and ' . (count($groups) - 1) . ' other groups';
			//}
			//$item['first_group'] = $firstGroupMessage;
			//$item['groups'] = implode(', ', $groups);
			
			//if ($groups) {
			//	$item['readable_groups'] = ze\admin::phrase('Groups: [[groups]]', ['groups' => $item['groups']]);
			//} else {
			//	$item['readable_groups'] = ze\admin::phrase('Groups: None');
			//}
			
		}
	
		//Set a title
		if ($refinerName == 'group_members') {
			$groupDetails = zenario_users::getGroupDetails($refinerId);
				
			$panel['title'] = ze\admin::phrase('Members of the group "[[label]]"', $groupDetails);
			$panel['no_items_message'] = ze\admin::phrase('This group has no members.');
			$panel['item_buttons']['remove_users_from_this_group']['ajax']['confirm']['message'] = str_replace(['<<', '>>'], ['[[', ']]'], ze\admin::phrase('Are you sure you wish to remove the user/contact "<<identifier>>" from the group "[[label]]"?', ['label' => $groupDetails['label']]));
			ze\lang::applyMergeFields($panel['item_buttons']['remove_users_from_this_group']['ajax']['confirm']['multiple_select_message'], ['label' => $groupDetails['label'], 'item_count' => '[[item_count]]']);
		} elseif ($refinerName == 'smart_group') {
			$groupDetails = ze\smartGroup::details($refinerId);
				
			if ($groupDetails['intended_usage'] == 'smart_newsletter_group') {
				$panel['title'] = ze\admin::phrase('Members of smart newsletter group "[[name]]"', $groupDetails);
			} else {
				$panel['title'] = ze\admin::phrase('Members of smart group "[[name]]"', $groupDetails);
			}
			$panel['no_items_message'] = ze\admin::phrase('This smart group has no members.');
		}
	
		//Don't show the "Create User" or "Delete User" or "Import" buttons on a refiner
		if ($refinerName) {
			if ($refinerName == 'suspended_users') {
				unset($panel['collection_buttons']['add']);
				unset($panel['collection_buttons']['import_dropdown']);
				unset($panel['quick_filter_buttons']);
				
			} else {
				unset($panel['collection_buttons']['add']);
				if ($refinerName == 'group_members' || $refinerName == 'smart_group') {
					//unset($panel['item_buttons']['delete']);
				} else {
					unset($panel['item_buttons']['delete']);
				}
				unset($panel['collection_buttons']['import_dropdown']);
			}
			
		}
	
		if ($refinerName == 'group_members') {
			unset($panel['item_buttons']['add_users_to_groups']);
			unset($panel['item_buttons']['remove_users_from_groups']);
		}
		
		switch($refinerName){
			case 'suspended_users':
				$panel['title'] = ze\admin::phrase('Suspended users');
				$panel['no_items_message'] = 'No suspended users.';
				unset($panel['trash']);
				unset($panel['quick_filter_buttons']['all']);
				unset($panel['quick_filter_buttons']['pending']);
				unset($panel['quick_filter_buttons']['active']);
				unset($panel['quick_filter_buttons']['contact']);
				
				break;
			
			case 'active_users':
				$panel['title'] = ze\admin::phrase('Active users');
				$panel['no_items_message'] = 'No extranet users found with active status';
				unset($panel['trash']);
				unset($panel['quick_filter_buttons']['all']);
				unset($panel['quick_filter_buttons']['pending']);
				unset($panel['quick_filter_buttons']['active']);
				unset($panel['quick_filter_buttons']['contact']);
				
				break;
		}
		
		
		//If there are no results
		if (empty($panel['items'])) {
			//Find any encrypted/hashed columns...
			$cols = array_merge(self::getEncryptedColumns('users'), self::getEncryptedColumns('users_custom_data'));
	
	
			if (!empty($cols)) {
				//...and override the "no items in search" message.
				$noResultsMessage = 'There are no users/contacts matching your search. Please note: ';
				
				
				$encryptedColumns = $hashedColumns = [];
				foreach ($cols as $col) {
					//Give nice names to any encrypted or hashed columns
					if ($col->hashed == true) {
						$hashedColumns[] = ucwords(str_replace('_', ' ', $col->col));
					} else {
						$encryptedColumns[] = ucwords(str_replace('_', ' ', $col->col));
					}
				}
				
				if (!empty($encryptedColumns)) {
					$encryptedColumnsMessage = ze\admin::phrase("\n\n". 'The column(s) ' . implode(', ', $encryptedColumns) . ' are encrypted and cannot be searched.');
					$noResultsMessage .= $encryptedColumnsMessage;
				}
				
				if (!empty($hashedColumns)) {
					$hashedColumnsMessage = ze\admin::phrase("\n\n". 'The column(s) ' . implode(', ', $hashedColumns) . ' are encrypted and hashed. They can only be searched with exact matches.');
					$noResultsMessage .= $hashedColumnsMessage;
				}
				
				$panel['no_items_in_search_message'] = $noResultsMessage;
			}
		}
	}
	
	public function handleOrganizerPanelAJAX($path, $ids, $ids2, $refinerName, $refinerId) {
		
		if (ze::post('delete_user') && ze\priv::check('_PRIV_EDIT_USER')) {
			foreach (explode(',', $ids) as $id) {
				ze\userAdm::delete($id);
			}
		
		} elseif (ze::post('remove_users_from_this_group') && ze::post('refiner__group_members') && ze\priv::check('_PRIV_EDIT_USER')) {
			foreach (explode(',', $ids) as $id) {
				ze\user::addToGroup($id, ze::post('refiner__group_members'), $remove = true);
			}
	
		} elseif (ze::post('add_user_to_this_group') && ze::post('refiner__group_members') && ze\priv::check('_PRIV_EDIT_USER')) {
			foreach (explode(',', $ids) as $userId) {
				ze\user::addToGroup($userId, ze::post('refiner__group_members'));
			}
		} elseif (ze::post('suspend_user') && ze\priv::check('_PRIV_EDIT_USER')) {
			foreach (explode(',', $ids) as $id) {
				ze\userAdm::suspend($id, $adminFacing = true);
			}
			
			ze\escape::bFlag('TOAST_TYPE', 'success');
			ze\escape::bFlag('TOAST_MESSAGE', ze\admin::phrase('Item saved, but your filter prevents it from appearing'));
			
			
		//Set a new avatar for a User/Users
		} elseif (ze::post('upload_image') && ze\priv::check('_PRIV_EDIT_USER')) {
			zenario_users::uploadUserImage($ids);
		//Remove the image for each user
		} elseif (ze::post('delete_image') && ze\priv::check('_PRIV_EDIT_USER')) {
			zenario_users::deleteUserImage($ids);
		} elseif (ze::post('convert_to_contact') && ze\priv::check('_PRIV_EDIT_USER')) {
			foreach (explode(',', $ids) as $id) {
				ze\userAdm::convertToContact($id);
				
				$cols = [
					'last_edited_admin_id' => ze\admin::id(),
					'modified_date' => ze\date::now(),
					'last_edited_user_id' => null,
					'last_edited_username' => null
				];
				
				ze\userAdm::save($cols, $id);
				
				ze\module::sendSignal("eventUserStatusChange", ["userId" => $id, "status" => "contact"]);
			}
		
		}
	}
}
