<?php
if (!defined("ROOT_PATH"))
{
	header("HTTP/1.1 403 Forbidden");
	exit;
}
class pjAdminOptions extends pjAdmin
{
	private function getSafeOptionsAction()
	{
		$action = $this->_post->check('next_action') ? $this->_post->toString('next_action') : 'pjActionBooking';
		$allowed = array(
			'pjActionBooking',
			'pjActionGrid',
			'pjActionBookingForm',
			'pjActionTerm',
			'pjActionShippingTax'
		);
		return in_array($action, $allowed, true) ? $action : 'pjActionBooking';
	}

	private function isValidCsrfToken()
	{
		$token = '';
		if ($this->_post->check('csrf_token')) {
			$token = $this->_post->toString('csrf_token');
		} elseif ($this->_get->check('csrf_token')) {
			$token = $this->_get->toString('csrf_token');
		} elseif (!empty($_SERVER['HTTP_X_CSRF_TOKEN'])) {
			$token = $_SERVER['HTTP_X_CSRF_TOKEN'];
		}
		return !empty($_SESSION['csrf_token']) && !empty($token) && hash_equals($_SESSION['csrf_token'], $token);
	}

	public function pjActionUpdate()
	{
		$this->checkLogin();

		if (!pjAuth::factory()->hasAccess())
		{
			$this->sendForbidden();
			return;
		}
		
		if (self::isPost() && $this->_post->toInt('options_update'))
		{
			if (!$this->isValidCsrfToken())
			{
				pjUtil::redirect($_SERVER['PHP_SELF'] . "?controller=pjAdminOptions&action=" . $this->getSafeOptionsAction() . "&err=AOPCSRF");
			}
			$pjOptionModel = new pjOptionModel();
			$nextAction = $this->_post->toString('next_action');
			if ($nextAction === 'pjActionBooking') {
				$pjOptionModel
					->where('foreign_id', $this->getForeignId())
					->where('type', 'bool')
					->where('tab_id', $this->_post->toInt('tab'))
					->modifyAll(array('value' => '1|0::0'));
				$pjOptionModel->reset()
					->where('foreign_id', $this->getForeignId())
					->whereIn('`key`', array('o_disable_orders','o_disable_payments','o_allow_demo_purchases'))
					->modifyAll(array('value' => 'Yes|No::No'));
			} elseif ($this->_post->toInt('tab') == 6) {
				$pjOptionModel
					->where('foreign_id', $this->getForeignId())
					->where('type', 'bool')
					->where('tab_id', $this->_post->toInt('tab'))
					->modifyAll(array('value' => '1|0::0'));
				$pjMultiLangModel = pjMultiLangModel::factory();
				$pjTaxModel = pjTaxModel::factory();
				$shipping_arr = $this->_post->toArray('shipping');
				$free_arr = $this->_post->toArray('free');
				$tax_arr = $this->_post->toArray('tax');
				foreach ($shipping_arr as $k => $v)
				{
					if (strpos($k, "new_") === 0)
					{
						# Insert
						$insert_id = $pjTaxModel->reset()->setAttributes(array(
							'shipping' => $shipping_arr[$k],
							'free' => $free_arr[$k],
							'tax' => $tax_arr[$k]
						))->insert()->getInsertId();
						
						if ($insert_id !== false && (int) $insert_id > 0)
						{
							if ($this->_post->toArray('i18n'))
							{
								$tmp = $this->pjActionTurnI18n($this->_post->toArray('i18n'), 'location', $k);
								$pjMultiLangModel->reset()->saveMultiLang($tmp, $insert_id, 'pjTax', 'data');
							}
						}
					} else {
						# Update
						$pjTaxModel->reset()->set('id', $k)->modify(array(
							'shipping' => $shipping_arr[$k],
							'free' => $free_arr[$k],
							'tax' => $tax_arr[$k]
						));
						
						if ($this->_post->toArray('i18n'))
						{
							$tmp = $this->pjActionTurnI18n($this->_post->toArray('i18n'), 'location', $k);
							$pjMultiLangModel->reset()->updateMultiLang($tmp, $k, 'pjTax', 'data');
						}
					}
				}
			}
			foreach ($this->_post->raw() as $key => $value)
			{
				if (preg_match('/value-(string|text|int|float|enum|bool|color)-(.*)/', $key) === 1)
				{
					list(, $type, $k) = explode("-", $key);
					if (!empty($k))
					{
						$_value = ':NULL';
						if ($value)
						{
							switch ($type)
							{
								case 'string':
								case 'text':
								case 'enum':
								case 'color':
									$_value = $this->_post->toString($key);
									break;
								case 'int':
								case 'bool':
									$_value = $this->_post->toString($key);
									break;
								case 'float':
								    $_value = $this->_post->toString($key);
									break;
							}
						}
			
						$pjOptionModel
						->reset()
						->where('foreign_id', $this->getForeignId())
						->where('`key`', $k)
						->limit(1)
						->modifyAll(array('value' => $_value));
					}
				}
			}
			
			$i18n_arr = $this->_post->toI18n('i18n');
			if (!empty($i18n_arr) && $this->_post->toInt('tab') != 6)
			{
				pjMultiLangModel::factory()->updateMultiLang($i18n_arr, $this->getForeignId(), 'pjOption', 'data');
			}
			
			$err = '';
			if ($this->_post->check('next_action'))
			{
				switch ($this->_post->toString('next_action'))
				{
					case 'pjActionBooking':
					case 'pjActionGrid':
						$err = 'AOP02';
						break;
					case 'pjActionBookingForm':
						$err = 'AOP03';
						break;
					case 'pjActionTerm':
						$err = 'AOP04';
						break;
					case 'pjActionShippingTax':
						$err = 'AOP06';
						break;
					
				}
			}
			pjUtil::redirect($_SERVER['PHP_SELF'] . "?controller=pjAdminOptions&action=" . $this->_post->toString('next_action') . "&err=$err");
		}

		pjUtil::redirect($_SERVER['PHP_SELF'] . "?controller=pjAdminOptions&action=pjActionBooking");
	}
	
	public function pjActionBooking()
	{
		if (!pjAuth::factory()->hasAccess())
		{
			$this->sendForbidden();
			return;
		}
		$arr = pjOptionModel::factory()
            ->where('t1.foreign_id', $this->getForeignId())
            ->where('t1.tab_id', 2)
            ->orderBy('t1.order ASC')
            ->findAll()
            ->getData();

        $this->set('arr', $arr);
        $this->appendJs('pjAdminOptions.js');
	}

	public function pjActionGrid()
	{
		if (!pjAuth::factory()->hasAccess())
		{
			$this->sendForbidden();
			return;
		}
		$arr = pjOptionModel::factory()
            ->where('t1.foreign_id', $this->getForeignId())
            ->where('t1.tab_id', 2)
            ->orderBy('t1.order ASC')
            ->findAll()
            ->getData();

        $this->set('arr', $arr);
        $this->appendJs('pjAdminOptions.js');
	}
	
	public function pjActionBookingForm()
	{
		if (!pjAuth::factory()->hasAccess())
		{
			$this->sendForbidden();
			return;
		}
	
		$arr = pjOptionModel::factory()
		->where('t1.foreign_id', $this->getForeignId())
		->where('t1.tab_id', 3)
		->orderBy('t1.order ASC')
		->findAll()
		->getData();
	
		$this->set('arr', $arr);
		$this->appendJs('pjAdminOptions.js');
	}
	
	public function pjActionTerm()
	{
		if (!pjAuth::factory()->hasAccess())
		{
			$this->sendForbidden();
			return;
		}
		
		$arr = pjOptionModel::factory()
				->where('t1.foreign_id', $this->getForeignId())
				->where('t1.tab_id', 4)
				->orderBy('t1.order ASC')
				->findAll()
				->getData();
	
		$arr['i18n'] = pjMultiLangModel::factory()->getMultiLang($this->getForeignId(), 'pjOption');
	
		$this->set('arr', $arr);
	
		$this->setLocalesData();
	
		$this->appendJs('jquery.multilang.js', $this->getConstant('pjBase', 'PLUGIN_JS_PATH'), false, false);
		$this->appendJs('tinymce.min.js', PJ_THIRD_PARTY_PATH . 'tinymce/');
		$this->appendJs('pjAdminOptions.js');
	}
	
	public function pjActionNotifications()
	{
		if (!pjAuth::factory()->hasAccess())
		{
			$this->sendForbidden();
			return;
		}
		
		$arr = pjOptionModel::factory()
				->where('t1.foreign_id', $this->getForeignId())
				->where('t1.tab_id', 3)
				->orderBy('t1.order ASC')
				->findAll()
				->getData();
	
		$arr['i18n'] = pjMultiLangModel::factory()->getMultiLang($this->getForeignId(), 'pjOption');
	
		$this->set('arr', $arr);
	
		$this->setLocalesData();
	
		$this->appendCss('awesome-bootstrap-checkbox.css', PJ_THIRD_PARTY_PATH . 'awesome_bootstrap_checkbox/');
		$this->appendJs('jquery.multilang.js', $this->getConstant('pjBase', 'PLUGIN_JS_PATH'), false, false);
		$this->appendJs('tinymce.min.js', PJ_THIRD_PARTY_PATH . 'tinymce/');
		$this->appendJs('pjAdminOptions.js');
	}
	
	public function pjActionInstall()
	{
		if (!pjAuth::factory()->hasAccess())
		{
			$this->sendForbidden();
			return;
		}
		
		if (self::isPost()) {
			foreach ($this->_post->raw() as $key => $value) {
				pjOptionModel::factory()
					->where('`key`', $key)
					->modifyAll(array('value' => $value));
			}

			pjUtil::redirect('index.php?controller=pjAdminOptions&action=pjActionInstall&err=AO01');
		}
		
		$this->set('category_arr', pjCategoryModel::factory()->getNode($this->getLocaleId(), 1));
		
		$this->set('is_flag_ready', $this->requestAction(array('controller' => 'pjBaseLocale', 'action' => 'pjActionIsFlagReady'), array('return')));
		$locale_arr = pjBaseLocaleModel::factory()
			->select('t1.*, t2.file, t2.title')
			->join('pjBaseLocaleLanguage', 't2.iso=t1.language_iso', 'left')
			->where('t2.file IS NOT NULL')
			->orderBy('t1.sort ASC')
			->findAll()
			->getData();
		$this->set('locale_arr', $locale_arr);
				
		$this->appendJs('pjAdminOptions.js');
	}
	
	public function pjActionNotificationsGetMetaData()
	{
		$this->setAjax(true);
		
		if (!$this->isXHR())
		{
			self::jsonResponse(array('status' => 'ERR', 'code' => 100, 'text' => 'Missing headers.'));
		}
		
		if (!self::isGet())
		{
			self::jsonResponse(array('status' => 'ERR', 'code' => 101, 'text' => 'Invalid request.'));
		}
		
		if (!(isset($this->query['recipient']) && pjValidation::pjActionNotEmpty($this->query['recipient'])))
		{
			self::jsonResponse(array('status' => 'ERR', 'code' => 102, 'text' => 'Missing, empty or invalid parameters.'));
		}
		
		$this->set('arr', pjNotificationModel::factory()
			->where('t1.recipient', $this->query['recipient'])
		    ->orderBy("id ASC")
			->findAll()
			->getData());
	}
	
	public function pjActionNotificationsGetContent()
	{
		$this->setAjax(true);
		
		if (!$this->isXHR())
		{
			self::jsonResponse(array('status' => 'ERR', 'code' => 100, 'text' => 'Missing headers.'));
		}
		
		if (!self::isGet())
		{
			self::jsonResponse(array('status' => 'ERR', 'code' => 101, 'text' => 'Invalid request.'));
		}
		
		if (!($this->_get->check('recipient') && $this->_get->check('variant') && $this->_get->check('transport'))
			&& pjValidation::pjActionNotEmpty($this->_get->toString('recipient'))
			&& pjValidation::pjActionNotEmpty($this->_get->toString('variant'))
			&& pjValidation::pjActionNotEmpty($this->_get->toString('transport'))
			&& in_array($this->_get->toString('transport'), array('email', 'sms'))
		)
		{
			self::jsonResponse(array('status' => 'ERR', 'code' => 102, 'text' => 'Missing, empty or invalid parameters.'));
		}
		
		$arr = pjNotificationModel::factory()
			->where('t1.recipient', $this->_get->toString('recipient'))
			->where('t1.variant', $this->_get->toString('variant'))
			->where('t1.transport', $this->_get->toString('transport'))
			->limit(1)
			->findAll()
			->getDataIndex(0);
		
		if (!$arr)
		{
			self::jsonResponse(array('status' => 'ERR', 'code' => 103, 'text' => 'Message not found.'));
		}
		
		$arr['i18n'] = pjBaseMultiLangModel::factory()->getMultiLang($arr['id'], 'pjNotification');
		$this->set('arr', $arr);
		
		# Check SMS
		$this->set('is_sms_ready', (isset($this->option_arr['plugin_sms_api_key']) && !empty($this->option_arr['plugin_sms_api_key']) ? 1 : 0));
		
		# Get locales
		$locale_arr = pjBaseLocaleModel::factory()
			->select('t1.*, t2.file, t2.title')
			->join('pjBaseLocaleLanguage', 't2.iso=t1.language_iso', 'left')
			->where('t2.file IS NOT NULL')
			->orderBy('t1.sort ASC')
			->findAll()
			->getData();
		
		$lp_arr = array();
		foreach ($locale_arr as $item)
		{
			$lp_arr[$item['id']."_"] = array($item['file'], $item['title']);
		}
		$this->set('lp_arr', $locale_arr);
		$this->set('locale_str', self::jsonEncode($lp_arr));
		$this->set('is_flag_ready', $this->requestAction(array('controller' => 'pjBaseLocale', 'action' => 'pjActionIsFlagReady'), array('return')));
	}
	
	public function pjActionNotificationsSetContent()
	{
		$this->setAjax(true);
		
		if (!$this->isXHR())
		{
			self::jsonResponse(array('status' => 'ERR', 'code' => 100, 'text' => 'Missing headers.'));
		}
		
		if (!self::isPost())
		{
			self::jsonResponse(array('status' => 'ERR', 'code' => 101, 'text' => 'Invalid request.'));
		}
		
		if (!(isset($this->body['id']) && pjValidation::pjActionNumeric($this->body['id'])))
		{
			self::jsonResponse(array('status' => 'ERR', 'code' => 102, 'text' => 'Missing, empty or invalid parameters.'));
		}
		
		$isToggle = $this->_post->check('is_active') && in_array($this->_post->toInt('is_active'), array(1,0));
		$isFormSubmit = $this->_post->check('i18n') && !$this->_post->isEmpty('i18n');
		
		if (!($isToggle xor $isFormSubmit))
		{
			self::jsonResponse(array('status' => 'ERR', 'code' => 103, 'text' => 'Data mismatch.'));
		}
		
		if ($isToggle)
		{
			pjNotificationModel::factory()
				->set('id', $this->_post->toInt('id'))
				->modify(array('is_active' => $this->_post->toInt('is_active')));
		} elseif ($isFormSubmit) {
			pjBaseMultiLangModel::factory()->updateMultiLang($this->_post->toArray('i18n'), $this->_post->toInt('id'), 'pjNotification');
		}
		
		self::jsonResponse(array('status' => 'OK', 'code' => 200, 'text' => 'Notification has been updated.'));
	}
	
	public function pjActionPreview()
	{
		$this->appendJs('pjAdminTheme.js');
	}

	public function pjActionSaveThemeColors()
	{
		$this->setAjax(true);

		if (!$this->isXHR())
		{
			self::jsonResponse(array('status' => 'ERR', 'code' => 100, 'text' => 'Missing headers.'));
		}
		if (!self::isPost())
		{
			self::jsonResponse(array('status' => 'ERR', 'code' => 101, 'text' => 'HTTP method not allowed.'));
		}
		pjAppController::validateCsrfToken();

		$foreignId = $this->getForeignId();
		$colorFields = array(
			'o_brand_color',
			'o_accent_color',
			'o_text_color',
			'o_background_color',
			'o_price_color',
			'o_page_background_color'
		);
		$stringFields = array('o_font_family', 'o_color_palette');

		foreach ($colorFields as $key)
		{
			if (!$this->_post->has($key))
			{
				continue;
			}
			$value = $this->_post->toString($key);
			if (!preg_match('/^#[0-9a-fA-F]{6}$/', $value))
			{
				continue;
			}
			$existing = pjOptionModel::factory()
				->where('t1.foreign_id', $foreignId)
				->where('t1.`key`', $key)
				->limit(1)
				->findAll()
				->getDataIndex(0);
			if (!empty($existing)) {
				pjOptionModel::factory()
					->where('foreign_id', $foreignId)
					->where('`key`', $key)
					->limit(1)
					->modifyAll(array('value' => $value));
			} else {
				pjOptionModel::factory()->setAttributes(array(
					'foreign_id' => $foreignId,
					'key' => $key,
					'value' => $value,
					'type' => 'string',
					'is_visible' => 0
				))->insert();
			}
		}

		foreach ($stringFields as $key)
		{
			if (!$this->_post->has($key))
			{
				continue;
			}
			$value = $this->_post->toString($key);
			if ($key === 'o_font_family')
			{
				$value = preg_replace('/[^a-zA-Z0-9\s]/', '', $value);
			}
			if ($key === 'o_color_palette')
			{
				$value = preg_replace('/[^0-9]/', '', $value);
			}
			$existing = pjOptionModel::factory()
				->where('t1.foreign_id', $foreignId)
				->where('t1.`key`', $key)
				->limit(1)
				->findAll()
				->getDataIndex(0);
			if (!empty($existing)) {
				pjOptionModel::factory()
					->where('foreign_id', $foreignId)
					->where('`key`', $key)
					->limit(1)
					->modifyAll(array('value' => $value));
			} else {
				pjOptionModel::factory()->setAttributes(array(
					'foreign_id' => $foreignId,
					'key' => $key,
					'value' => $value,
					'type' => 'string',
					'is_visible' => 0
				))->insert();
			}
		}

		self::jsonResponse(array('status' => 'OK', 'code' => 200, 'text' => 'Theme settings have been saved.'));
	}
	
	public function pjActionUpdateTheme()
	{
	    $this->setAjax(true);
	    
	    if (!$this->isXHR())
	    {
	        self::jsonResponse(array('status' => 'ERR', 'code' => 100, 'text' => 'Missing headers.'));
	    }
	    
	    if(!self::isPost())
	    {
	        self::jsonResponse(array('status' => 'ERR', 'code' => 101, 'text' => 'HTTP method not allowed.'));
	    }
	    
	    if (!$this->_post->has('theme'))
	    {
	        self::jsonResponse(array('status' => 'ERR', 'code' => 102, 'text' => 'Missing, empty or invalid parameters.'));
	    }
	    $theme = str_replace("theme", "", $this->_post->toString('theme'));
	    pjOptionModel::factory()
	    ->where('foreign_id', $this->getForeignId())
	    ->where('`key`', 'o_theme')
	    ->limit(1)
	    ->modifyAll(array('value' => '0|1|2|3|4|5|6|7|8|9|10::' . $theme));
	    
	    self::jsonResponse(array('status' => 'OK', 'code' => 200, 'text' => 'Theme has been changed.'));
	}
	
	public function pjActionShippingTax()
	{
		if (!pjAuth::factory()->hasAccess())
		{
			$this->sendForbidden();
			return;
		}
	
		$arr = pjTaxModel::factory()->findAll()->getData();
		foreach ($arr as $k => $v)
		{
			$arr[$k]['i18n'] = pjMultiLangModel::factory()->reset()->getMultiLang($v['id'], 'pjTax');
		}
	
		$this->set('arr', $arr);
	
		$this->setLocalesData();
	
		$this->appendJs('jquery.multilang.js', $this->getConstant('pjBase', 'PLUGIN_JS_PATH'), false, false);
		$this->appendCss('jasny-bootstrap.min.css', PJ_THIRD_PARTY_PATH . 'jasny/');
        $this->appendJs('jasny-bootstrap.min.js',  PJ_THIRD_PARTY_PATH . 'jasny/');
		$this->appendJs('pjAdminOptions.js');
	}
	
	private function pjActionTurnI18n($data, $key, $id, $index=NULL)
	{
		$arr = array();
		foreach ($data as $locale => $locale_arr)
		{
			$arr[$locale] = array(
				$key => is_null($index) ?
					(isset($locale_arr[$key]) && isset($locale_arr[$key][$id]) ? $locale_arr[$key][$id] : NULL) :
					(isset($locale_arr[$key]) && isset($locale_arr[$key][$id]) && isset($locale_arr[$key][$id][$index]) ? $locale_arr[$key][$id][$index] : NULL)
			);
		}
		
		return $arr;
	}
	
	public function pjActionDeleteLocation()
	{
		$this->setAjax(true);
	
		if (!$this->isXHR())
		{
		    self::jsonResponse(array('status' => 'ERR', 'code' => 100, 'text' => 'Missing headers.'));
		}
		if (!self::isPost())
		{
		    self::jsonResponse(array('status' => 'ERR', 'code' => 101, 'text' => 'HTTP method not allowed.'));
		}
		if (!pjAuth::factory()->hasAccess())
		{
		    self::jsonResponse(array('status' => 'ERR', 'code' => 102, 'text' => 'Access denied.'));
		}
		if (!($this->_post->toInt('id')))
		{
		    self::jsonResponse(array('status' => 'ERR', 'code' => 103, 'text' => 'Missing, empty or invalid parameters.'));
		}
		$id = $this->_post->toInt('id');
		$pjTaxModel = pjTaxModel::factory();
		$arr = $pjTaxModel->find($id)->getData(); 
		if(empty($arr))
		{
		    self::jsonResponse(array('status' => 'ERR', 'code' => 104, 'text' => 'Shipping location not found.'));
		}
		if ($pjTaxModel->reset()->set('id', $id)->erase()->getAffectedRows() == 1)
	    {
	        pjMultiLangModel::factory()->where('model', 'pjTax')->where('foreign_id', $id)->eraseAll();			
			self::jsonResponse(array('status' => 'OK', 'code' => 200, 'text' => 'Shipping location has been deleted'));
	    }else{
	        self::jsonResponse(array('status' => 'ERR', 'code' => 105, 'text' => 'Shipping location has not been deleted.'));
	    }
	}
	
	public function pjActionUpdate9720() {
	    $pjAuthRolePermissionModel = pjAuthRolePermissionModel::factory();
	    $pjAuthUserPermissionModel = pjAuthUserPermissionModel::factory();
	    
	    $permissions = pjAuthPermissionModel::factory()->findAll()->getDataPair('key', 'id');
	    
	    $user_arr = array();
	    $u_arr = pjAuthUserModel::factory()->whereIn('t1.role_id', array(1,2))->findAll()->getData();
	    if ($u_arr) {
	        $user_ids = array();
	        foreach ($u_arr as $val) {
	            $user_arr[$val['role_id']][] = $val['id'];
	            $user_ids[] = $val['id'];
	        }
	        $pjAuthUserPermissionModel->whereIn('user_id', $user_ids)->eraseAll();
	    }
	    $roles = array(1 => 'admin', 2 => 'editor');
	    foreach ($roles as $role_id => $role)
	    {
	        if (isset($GLOBALS['CONFIG'], $GLOBALS['CONFIG']["role_permissions_{$role}"])
	        && is_array($GLOBALS['CONFIG']["role_permissions_{$role}"])
	        && !empty($GLOBALS['CONFIG']["role_permissions_{$role}"]))
	        {
	            $pjAuthRolePermissionModel->reset()->where('role_id', $role_id)->eraseAll();
	            
	            foreach ($GLOBALS['CONFIG']["role_permissions_{$role}"] as $role_permission)
	            {
	                if($role_permission == '*')
	                {
	                    // Grant full permissions for the role
	                    foreach($permissions as $key => $permission_id)
	                    {
	                        $pjAuthRolePermissionModel->setAttributes(compact('role_id', 'permission_id'))->insert();
	                        if (isset($user_arr[$role_id])) {
	                            foreach ($user_arr[$role_id] as $user_id) {
	                                $pjAuthUserPermissionModel->reset()->setAttributes(array('user_id' => $user_id, 'permission_id' => $permission_id))->insert();
	                            }
	                        }
	                    }
	                    break;
	                }
	                else
	                {
	                    $hasAsterix = strpos($role_permission, '*') !== false;
	                    if($hasAsterix)
	                    {
	                        $role_permission = str_replace('*', '', $role_permission);
	                    }
	                    
	                    foreach($permissions as $key => $permission_id)
	                    {
	                        if($role_permission == $key || ($hasAsterix && strpos($key, $role_permission) !== false))
	                        {
	                            $pjAuthRolePermissionModel->setAttributes(compact('role_id', 'permission_id'))->insert();
	                            if (isset($user_arr[$role_id])) {
	                                foreach ($user_arr[$role_id] as $user_id) {
	                                    $pjAuthUserPermissionModel->reset()->setAttributes(array('user_id' => $user_id, 'permission_id' => $permission_id))->insert();
	                                }
	                            }
	                        }
	                    }
	                }
	            }
	        }
	    }
	    
	    echo 'Data updated!';
	    exit;
	}
	public function pjActionInvoiceTemplate()
	{
		if (!isset($_SESSION['admin_user']) || (int) $_SESSION['admin_user']['role_id'] !== 1) {
			pjUtil::redirect(PJ_INSTALL_URL . 'index.php');
		}

		if (self::isPost() && $this->_post->check('save_template_post')) {
			// Save settings JSON
			$raw = $this->_post->toArray('settings');
			$settings = array(
				'header_logo_position' => isset($raw['header_logo_position']) ? $raw['header_logo_position'] : 'left',
				'show_metadata' => array(
					'number'       => !empty($raw['show_metadata']['number']) ? 1 : 0,
					'issue_date'   => !empty($raw['show_metadata']['issue_date']) ? 1 : 0,
					'due_date'     => !empty($raw['show_metadata']['due_date']) ? 1 : 0,
					'status'       => !empty($raw['show_metadata']['status']) ? 1 : 0,
					'order_number' => !empty($raw['show_metadata']['order_number']) ? 1 : 0,
				),
				'show_customer' => array(
					'billing'    => !empty($raw['show_customer']['billing']) ? 1 : 0,
					'shipping'   => !empty($raw['show_customer']['shipping']) ? 1 : 0,
					'vat_number' => !empty($raw['show_customer']['vat_number']) ? 1 : 0,
					'coc_number' => !empty($raw['show_customer']['coc_number']) ? 1 : 0,
				),
				'show_items_columns' => array(
					'image'       => !empty($raw['show_items_columns']['image']) ? 1 : 0,
					'description' => !empty($raw['show_items_columns']['description']) ? 1 : 0,
					'qty'         => !empty($raw['show_items_columns']['qty']) ? 1 : 0,
					'unit_price'  => !empty($raw['show_items_columns']['unit_price']) ? 1 : 0,
					'line_total'  => !empty($raw['show_items_columns']['line_total']) ? 1 : 0,
				),
				'show_totals' => array(
					'subtotal' => !empty($raw['show_totals']['subtotal']) ? 1 : 0,
					'discount' => !empty($raw['show_totals']['discount']) ? 1 : 0,
					'shipping' => !empty($raw['show_totals']['shipping']) ? 1 : 0,
					'vat_high' => !empty($raw['show_totals']['vat_high']) ? 1 : 0,
					'vat_low'  => !empty($raw['show_totals']['vat_low']) ? 1 : 0,
					'total'    => !empty($raw['show_totals']['total']) ? 1 : 0,
				),
				'show_payment_instructions' => !empty($raw['show_payment_instructions']) ? 1 : 0,
				'show_footer_notes'         => !empty($raw['show_footer_notes']) ? 1 : 0,
				'raw_html_mode'             => !empty($raw['raw_html_mode']) ? 1 : 0,
			);

			// Upsert settings option
			$existing = pjOptionModel::factory()->where('t1.foreign_id', 1)->where('t1.`key`', 'o_invoice_template_settings')->limit(1)->findAll()->getDataIndex(0);
			if (!empty($existing['foreign_id'])) {
				pjOptionModel::factory()->where('foreign_id', 1)->where('`key`', 'o_invoice_template_settings')->limit(1)->modifyAll(array('value' => json_encode($settings)));
			} else {
				pjOptionModel::factory()->setAttributes(array(
					'foreign_id' => 1, 'key' => 'o_invoice_template_settings', 'tab_id' => 0,
					'value' => json_encode($settings), 'label' => 'Invoice template settings', 'type' => 'text',
					'order' => 0, 'is_visible' => 0, 'style' => '',
				))->insert();
			}

			// Save invoice labels.
			if ($this->_post->check('i18n')) {
				pjAppController::validateCsrfToken();
				$i18n = $this->_post->toArray('i18n');
				pjMultiLangModel::factory()->updateMultiLang($i18n, 1, 'pjInvoiceTemplate');
			}

			// Save custom template HTML using the built-in PHPJabbers invoice tokens.
			if ($this->_post->check('invoice_template')) {
				pjAppController::validateCsrfToken();
				$tpl = $this->_post->toString('invoice_template');
				if (strlen(trim($tpl)) >= 50 && strpos($tpl, '{{') === false) {
					$existing = pjOptionModel::factory()->where('t1.foreign_id', 1)->where('t1.`key`', 'o_invoice_template')->limit(1)->findAll()->getDataIndex(0);
					if (!empty($existing['foreign_id'])) {
						pjOptionModel::factory()->where('foreign_id', 1)->where('`key`', 'o_invoice_template')->limit(1)->modifyAll(array('value' => $tpl));
					} else {
						pjOptionModel::factory()->setAttributes(array(
							'foreign_id' => 1, 'key' => 'o_invoice_template', 'tab_id' => 0,
							'value' => $tpl, 'label' => 'Invoice template (HTML)', 'type' => 'text',
							'order' => 0, 'is_visible' => 0, 'style' => '',
						))->insert();
					}
				}
			}

			$activeLang = (int) $this->_post->toInt('active_locale');
			$langSuffix = $activeLang > 0 ? '&lang=' . $activeLang : '';
			pjUtil::redirect(PJ_INSTALL_URL . 'index.php?controller=pjAdminOptions&action=pjActionInvoiceTemplate&saved=1' . $langSuffix);
		}

		// Load data for the view.
		$this->set('settings', pjAppController::getInvoiceTemplateSettings());
		$this->set('template_html', pjAppController::getInvoiceTemplate());

		// Locales for the label editor.
		$locales = pjLocaleModel::factory()
			->select('t1.*, t2.file')
			->join('pjLocaleLanguage', 't2.iso=t1.language_iso', 'left outer')
			->where('t2.file IS NOT NULL')
			->orderBy('t1.sort ASC')
			->findAll()->getData();
		$this->set('locale_arr', $locales);

		// Labels per locale (custom + defaults).
		$labels_by_locale = array();
		foreach ($locales as $loc) {
			$labels_by_locale[$loc['id']] = pjAppController::getInvoiceLabels($loc['id']);
		}
		$this->set('labels_by_locale', $labels_by_locale);

		$this->set('is_flag_ready', $this->requestAction(array('controller' => 'pjLocale', 'action' => 'pjActionIsFlagReady'), array('return')));
	}

	/**
	 * Reset the invoice template to default. AJAX POST.
	 */
	public function pjActionResetInvoiceTemplate()
	{
		if (!self::isPost()) {
			self::jsonResponse(array('status' => 'ERR', 'code' => 100));
		}
		pjOptionModel::factory()->where('foreign_id', 1)->where('`key`', 'o_invoice_template')->limit(1)->eraseAll();
		self::jsonResponse(array('status' => 'OK', 'code' => 200, 'text' => 'Template restored.'));
	}

	/**
	 * Preview the invoice template with sample data and return PDF bytes.
	 */
	public function pjActionPreviewInvoiceTemplate()
	{
		if (!isset($_SESSION['admin_user']) || (int) $_SESSION['admin_user']['role_id'] !== 1) {
			pjUtil::redirect(PJ_INSTALL_URL . 'index.php');
			return;
		}
		$this->setLayout('pjActionEmpty');

		// Try an existing invoice first for a realistic preview.
		$real_invoice = pjInvoiceModel::factory()
			->select("t1.*, t2.content as b_country_title, t3.content as s_country_title")
			->join('pjMultiLang', "t2.model='pjBaseCountry' AND t2.foreign_id=t1.b_country_id AND t2.field='name' AND t2.locale=t1.locale_id", 'left outer')
			->join('pjMultiLang', "t3.model='pjBaseCountry' AND t3.foreign_id=t1.s_country_id AND t3.field='name' AND t3.locale=t1.locale_id", 'left outer')
			->orderBy('t1.id DESC')
			->limit(1)
			->findAll()
			->getDataIndex(0);

		// Use ?lang=X from the URL for preview language, otherwise default.
		$preview_locale = $this->_get->toInt('lang');
		if ($preview_locale <= 0) { $preview_locale = $this->getLocaleId(); }

		if (!empty($real_invoice['id'])) {
			$items = pjInvoiceItemModel::factory()->where('t1.invoice_id', $real_invoice['id'])->findAll()->getData();
			$html = pjAppController::buildInvoiceFromTemplate($real_invoice, $items, $this->option_arr, $preview_locale);
		} else {
			$dummy = array(
				'uuid' => 'SAMPLE-001', 'order_id' => 'XX1234567890', 'issue_date' => date('Y-m-d'),
				'due_date' => date('Y-m-d'), 'status' => 'not_paid', 'locale_id' => $preview_locale,
				'price' => 100.00, 'discount' => 10.00, 'shipping' => 5.00, 'insurance' => 0, 'total' => 95.00,
				'b_name' => 'John Smith',
				'b_address_1' => 'Sample Street 12', 'b_zip' => '1000 AA', 'b_city' => 'New York',
				'b_country_title' => 'United States', 'b_email' => 'john.smith@example.com',
				'notes' => 'Sample invoice with test data.',
			);
			$items = array(
				array('name' => 'White T-shirt size L', 'description' => 'Item T001-WHT-L', 'qty' => 2, 'unit_price' => 25.00, 'amount' => 50.00),
				array('name' => 'Blue trousers size 32', 'description' => '', 'qty' => 1, 'unit_price' => 50.00, 'amount' => 50.00),
			);
			$html = pjAppController::buildInvoiceFromTemplate($dummy, $items, $this->option_arr, $preview_locale);
		}

		// Generate PDF using the same footer approach as pjInvoice::renderInvoicePdf.
		$footerHtml = pjAppController::getInvoiceFooterHtml($this->option_arr, $preview_locale);

		$dm = new pjDependencyManager(PJ_INSTALL_PATH, PJ_THIRD_PARTY_PATH);
		$dm->load(PJ_CONFIG_PATH . 'dependencies.php')->resolve();
		require_once $dm->getPath('tcpdf') . 'tcpdf.php';
		require_once PJ_INSTALL_PATH . 'app/classes/pjInvoicePdf.class.php';

		$pdf = new pjInvoicePdf(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
		$pdf->setInvoiceFooterHtml($footerHtml);
		$pdf->setPrintHeader(false);
		$pdf->setPrintFooter(true);
		$pdf->setFooterMargin(15);
		$pdf->setFooterFont(array('dejavusans', '', 8));
		$pdf->SetMargins(10, 10, 10);
		$pdf->SetAutoPageBreak(true, 28);
		$pdf->SetFont('dejavusans', '', 9);
		$pdf->AddPage();
		$pdf->writeHTML($html, true, false, true, false, '');

		while (ob_get_level()) { ob_end_clean(); }
		header('Content-Type: application/pdf');
		header('Content-Disposition: inline; filename="invoice_preview.pdf"');
		echo $pdf->Output('invoice_preview.pdf', 'S');
		exit;
	}

}
?>
