<?php
namespace Controllers;

// Контроллер работы с API Агорты
class Api extends Controller {
	public $api_data, $auto_sinch=0, $neworders=0;

	public function __construct() {
		parent::__construct();
		$this->model=new \Models\Api($this->f3, $this->api_data['domen'], $this->api_data['pass'], $this->api_data['store_id'], $this->api_data['count']);
	}

	// Установка СНО
	function sno() {
		$res['success']=true;
		$txt='';
		$time_start=microtime(true)+rand(1, 999999)/1000000;
		$this->db->exec('UPDATE synchronization SET time_start=?', $time_start);
		$sno=$this->model->sno();
		if($sno['success']===true) {
			$r=$this->db->exec("UPDATE fr_settings SET sno=?", $sno['sno']);
			if($r>=0) {
				$txt=$this->messages->message('save_successful')['txt'];
			}
		}
		else { // если ответ от сервера не успешный
			$txt='';
			foreach ($sno['error'] as $er) {
				$txt.=$this->messages->message($er)['txt'].'<br>';
			}
			if(!$sno['debug'])$sno['debug']=array();
			$res['debug']=$sno['debug'];
			$res['success']=false;
			if($sno['success']===false) {
				$this->logs->save_log($txt.implode(';<br>', $res['debug']));
			}
		}

		$res['txt']=$txt;
		$this->db->exec('UPDATE synchronization SET time_start=0');

		echo json_encode($res);
		exit();
	}

	// Функция синхронизации пользователей
	function users() {
		$res['success']=true;
		if($this->f3->get('GET.reload')) {
			$res['reload']='.users_list';
			$res['close_all_window']=true;
		}
		$txt='';
		$time_start=microtime(true)+rand(1, 999999)/1000000;
		$this->db->exec('UPDATE synchronization SET time_start=?', $time_start);
		$users=$this->model->users(); // получаем пользователей
		if($users['success']===true) { // если все получили
			// Добавляем группы
			$sql="INSERT OR REPLACE INTO `usergroups` (`id`, `title`, `module`) VALUES ";
			$val=array();
			$in='';
			$val_in=array();
			// Формируем запросы на добавление, изменение или удаление групп
			foreach ($users['usergroups'] as $group) {
				if(!empty($val)) {
					$sql.=', ';
					$in.=', ';
				}
				$sql.="(?, ?, ?)";
				$in.='?';
				$val[]=$group['id'];
				$val[]=$group['title'];
				$val[]=$group['module'];
				$val_in[]=$group['id'];
			}
			// Выполняем запросы
			$groups_res=$this->db->exec($sql, $val);
			if($groups_res!==false) {
				$sql="DELETE FROM `usergroups` WHERE `id` NOT IN (".$in.")";
				$this->db->exec($sql, $val_in);
			}
			else {
				$mess=$this->messages->message('save_usergroups_error')['txt'];
				$res['success']=false;
				$txt.='<span class="false">'.$mess.'</span><br>';
			}


			// Добавляем пользователей
			$in='';
			$val_in=array();
			$u_sql=array();
			$u_val=array();
			foreach ($users['users'] as $user) {
				if(!empty($val_in)) {
					$in.=',';
				}
				$in.='?';
				$val_in[]=$user['id'];
				$sql="SELECT `id` FROM `users` WHERE `id`=? LIMIT 1";
				$u=$this->db->exec($sql, $user['id']);
				if(empty($u)) {
					$u_sql[]="INSERT INTO `users` (`id`, `name`, `short_name`, `group_id`, `pass`, `card`, `date_delete`, `hash`, `inn`, `type`, `kiosk`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
					$u_val[]=array(
						$user['id'],
						$user['name'],
						$user['short_name'],
						$user['group_id'],
						$user['pass'],
						$user['card'],
						$user['date_delete'],
						'',
						$user['inn'],
						$user['type'],
						$user['kiosk']
					);
				}
				else {
					$u_sql[]="UPDATE `users` SET `name`=?, `short_name`=?, `group_id`=?, `pass`=?, `card`=?, `date_delete`=?, `inn`=?, `type`=?, `kiosk`=? WHERE id=?";
					$u_val[]=array(
						$user['name'],
						$user['short_name'],
						$user['group_id'],
						$user['pass'],
						$user['card'],
						$user['date_delete'],
						$user['inn'],
						$user['type'],
						$user['kiosk'],
						$user['id']
					);
				}
			}

			// Выполняем запросы
			$users_res=$this->db->exec($u_sql, $u_val);
			if($users_res!==false) {
				$sql="DELETE FROM `users` WHERE `date_delete`<? AND `date_delete`>0";
				$this->db->exec($sql, strtotime('-15 days'));

				$sql="UPDATE `users` SET `date_delete`='".microtime(true)."' WHERE `date_delete`=0 AND `id` NOT IN (".$in.")";
				$this->db->exec($sql, $val_in);
			}
			else {
				$mess=$this->messages->message('save_users_error')['txt'];
				$res['success']=false;
				$txt.='<span class="false">'.$mess.'</span><br>';
			}

			if($txt=='') { // если текст сообщения еще не сформирован, то добавляем из последнего запроса
				$txt=$this->messages->message('success_users_synchronization')['txt'];
			}
			else {
				$this->logs->save_log($txt);
			}
		}
		else { // если ответ от сервера не успешный
			$txt='';
			foreach ($users['error'] as $er) {
				$txt.=$this->messages->message($er)['txt'].'<br>';
			}
			if(!$users['debug'])$users['debug']=array();
			$res['debug']=$users['debug'];
			$res['success']=false;
			if($users['success']===false) {
				$this->logs->save_log($txt.implode(';<br>', $res['debug']));
			}
		}

		$this->db->exec('UPDATE synchronization SET time_start=0, users_update=?', time());
		$res['txt']=$txt;
		$res['logs_n']=$this->f3->get('logs_n');
		$res['remote_receipts']=$this->f3->get('remote_receipts');
		$res['neworders']=$this->neworders;
		if($this->auto_sinch==1) {
			return $res;
		}
		else {
			echo json_encode($res);
			exit();
		}
	}

	// Загрузка категорий и товаров
	function products_load($time_update=0) {
		if(!is_numeric($time_update)) $tickets_update=0;
		$res['success']=true;
		$txt='';

		$data=$this->model->products($time_update); // загружаем продукты
		if($data['success']===true) {
			// Добавляем категории товаров
			$sql=array();
			$val=array();
			foreach ($data['categories'] as $cat) {
				$sql[]="INSERT OR REPLACE INTO productcategories (id, parent_id, title, color, date_delete, date_update, icon, show, img, kiosk_noshow) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
				if(!$cat['icon']) {
					$cat['icon']='';
				}
				if(!$cat['kiosk_noshow']) {
					$cat['kiosk_noshow']=0;
				}
				if($cat['date_delete']>0) {
					$cat['kassa_show']=0;
				}
				$val[]=array(
					$cat['id'],
					$cat['parent_id'],
					$cat['title'],
					$cat['color'],
					$cat['date_delete'],
					$cat['date_update'],
					$cat['icon'],
					$cat['kassa_show'],
					$cat['img'],
					$cat['kiosk_noshow']
				);
				$time_update=$cat['date_update'];
				if($sql_delete!='') $sql_delete.=', ';
				$sql_delete.='?';
				$val_delete[]=$cat['id'];
			}
			if(!empty($sql)) {
				if(!$this->db->exec($sql, $val)) {
					$txt.='<br>'.$this->messages->message('db_error')['txt'];
				}
				sleep(1);
			}
			$this->db->exec("DELETE FROM productcategories WHERE date_delete<? AND date_delete>0", time()-3600*24*14);

			// Добавляем товары и штрих-коды
			$sql=array();
			$val=array();
			$bsql=array();
			$bval=array();
			$dsql=array();
			$dval=array();
			foreach ($data['products'] as $prod) {
				if(!isset($prod['related'])) {
					$prod['related']='';
				}
				else {
					$prod['related']=json_encode($prod['related']);
				}
				$sql[]="INSERT OR REPLACE INTO products (id, code, ppr, fast, title, short_title, img, product_description, category_id, stock, price, buy_price, vat, vat_type, date_delete, date_update, marking, marking_group, egais, alcocode, quantity, print_group, print_group_id, related, max_discount, add_bonus, stop, combo_data, partner_id, units, sno, parent_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
				$val[]=array(
					$prod['id'],
					mb_strtoupper($prod['code']),
					$prod['ppr'],
					$prod['fast'],
					$prod['title'],
					$prod['short_title'],
					$prod['img'],
					$prod['description'],
					$prod['category_id'],
					$prod['stock'],
					$prod['price'],
					$prod['buy_price'],
					$prod['vat'],
					$prod['vat_type'],
					$prod['date_delete'],
					$prod['date_update'],
					$prod['marking'],
					$prod['marking_group'],
					$prod['egais'],
					$prod['alcocode'],
					$prod['quantity'],
					$prod['print_group'],
					$prod['print_group_id'],
					$prod['related'],
					$prod['max_discount'],
					$prod['add_bonus'],
					$prod['stop']?$prod['stop']:0,
					$prod['combo_data'],
					$prod['partner_id'],
					$prod['okei']?$prod['okei']:0,
					$prod['sno'],
					$prod['parent_id']?$prod['parent_id']:0
				);
				$dsql[]="DELETE FROM `barcodes` WHERE product_id=?";
				$dval[]=array($prod['id']);
				$time_update=$prod['date_update'];
				$barcodes=explode(',', $prod['barcodes']);
				if(!empty($barcodes)) {
					foreach ($barcodes as $barcode) {
						$bsql[]="INSERT OR REPLACE INTO barcodes (product_id, barcode) VALUES (?, ?)";
						$bval[]=array(
							$prod['id'],
							$barcode
						);
					}
				}

			}
			if(!empty($sql)) {
				if(!$this->db->exec($sql, $val)) {
					$txt.='<br>'.$this->messages->message('db_error')['txt'];
				}
				sleep(1);
			}
			if(!empty($dsql)) {
				$d=$this->db->exec($dsql, $dval);
				if($d===false) {
					$txt.='<br>'.$this->messages->message('db_error')['txt'];
				}
			}
			if(!empty($bsql)) {
				if(!$this->db->exec($bsql, $bval)) {
					$txt.='<br>'.$this->messages->message('db_error')['txt'];
				}
			}
			if($txt!='') {
				$this->logs->save_log($txt);
			}

			// Если массивы с продуктами и категориями были не пустые, то надо продолжить
			if(count($data['categories'])>0 || count($data['products'])>0) {
				$time=time();
				$this->db->exec('UPDATE synchronization SET time_start=?, time_update=?', array($time, $time_update));
				$txt.='<br>'.$this->messages->message('update')['txt'];
				$res['next_step']=$time;
			}
			else {
				$txt='<br>'.$this->messages->message('save_successful')['txt'];
				$this->db->exec('UPDATE synchronization SET time_start=?, time_update=?', array(0, $time_update));
			}

		}
		else { // Если произошла ошибка
			foreach ($data['error'] as $er) {
				$txt.=$this->messages->message($er)['txt'].'<br>';
			}
			$res['txt']=$txt;
			if(!$data['debug'])$data['debug']=array();
			$res['debug']=$data['debug'];
			$res['success']=false;
			if($data['success']===false) {
				$this->logs->save_log($txt.implode(';<br>', $res['debug']));
			}
			$this->db->exec('UPDATE synchronization SET time_start=?, time_update=?', array(0, $time_update));
		}
		$res['txt']=$txt;

		return $res;
	}

	// Загрузка обновленныйх категорий и товаров
	function products() {
		// Проверяем не запущена ли уже синхронизация.
		$sinch=$this->db->exec("SELECT * FROM synchronization WHERE time_start=0 OR time_start<".(time()-600)." LIMIT 1");
		if(!$sinch) {
			$res=array(
				'success'=>false,
				'txt'=>$this->messages->message('sync_is_already_running')['txt']
			);
		}
		else {
			$time_start=microtime(true)+rand(1, 999999)/1000000;
			$this->db->exec('UPDATE synchronization SET time_start=?', $time_start);
			$time_update=$sinch[0]['time_update'];
			$res=$this->products_load($time_update);
			if($this->f3->get('auto_sinch') && $res['success']) {
				$res['txt']=$this->messages->message('success_products_synchronization')['txt'];
			}
			$this->db->exec('UPDATE synchronization SET time_start=0');
		}
		$res['logs_n']=$this->f3->get('logs_n');
		$res['remote_receipts']=$this->f3->get('remote_receipts');
		if($this->auto_sinch==1) {
			return $res;
		}
		else {
			echo json_encode($res);
			exit();
		}
	}

	// Полная загрузка категорий и товаров
	function products_all() {
		$time_start=$this->f3->get('GET.time_start'); // Узнаем время запуска синхронизации
		if(!$time_start) $time_start=0; // если время не задано, то это начало синхронизации
		// Проверяем не запущена ли уже синхронизация.
		$sinch=$this->db->exec("SELECT * FROM synchronization LIMIT 1");
		if($sinch[0]['time_start']==$time_start || ($time_start==0 && $sinch[0]['time_start']<time()-600)) {
			if($time_start>0) { // Если синхронизация не только что началась, то время обновления берем из таблицы
				$time_update=$sinch[0]['time_update'];
			}
			else { // если синхронизация только что началась, то время обновления 0, чтобы получить все товары
				$time_update=0;
			}
			if($time_start==0) { // Если синхронизация только началась, то очищаем таблицы
				$this->db->exec('DELETE FROM productcategories');
				$this->db->exec('DELETE FROM products');
				$this->db->exec('DELETE FROM barcodes');
				$this->db->exec('VACUUM');
			}
			$this->db->exec('UPDATE synchronization SET time_start=?', array(time()));
			$res=$this->products_load($time_update);
		}
		else {
			$mess=$this->messages->message('sync_is_already_running');
			$res['txt']=$mess['txt'];
			$res['success']=false;
		}

		if($res['next_step']) {
			$res['next_step']='/api/products_all?time_start='.$res['next_step'];
		}
		echo json_encode($res);
		exit();
	}

	// Изменить статус заказа
	function change_order_status() {
		$get=$this->f3->get('GET');
		$res=$this->model->change_order_status($get['id'], $get['status_id']);
		if($res['success']===true) {
			$txt=$this->messages->message('save_successful')['txt'];
			$res['function']='save_order_status('.$get['status_id'].')';
		}
		else { // если ответ от сервера не успешный
			$txt='';
			foreach ($res['error'] as $er) {
				$txt.=$this->messages->message($er)['txt'].'<br>';
			}
			if(!$res['debug'])$res['debug']=array();
		}

		$res['txt']=$txt;
		echo json_encode($res);
		exit();
	}

	// Загрузка списка статусов заказов
	function ordersstatuses() {
		$res['success']=true;
		$txt='';

		$data=$this->model->ordersstatuses();
		if($data['success']===true) {
			$sql=array();
			$val=array();
			foreach ($data['status'] as $s) {
				$sql[]="INSERT OR REPLACE INTO ordersstatus (id, title) VALUES (?, ?)";
				$val[]=array(
					$s['id'],
					$s['title']
				);
			}
			if(!empty($sql)) {
				if(!$this->db->exec($sql, $val)) {
					$txt.='<br>'.$this->messages->message('db_error')['txt'];
				}
				sleep(1);
				$status_id=array_column($data['status'], 'id');
				$this->db->exec("DELETE FROM ordersstatus WHERE id NOT IN (".implode(", ",$status_id).")");
			}
			if($txt!='') {
				$this->logs->save_log($txt);
			}
			$txt='<br>'.$this->messages->message('save_successful')['txt'];
			$this->db->exec('UPDATE synchronization SET time_start=0, ordersstatuses=?', time());
		}
		else { // Если произошла ошибка
			foreach ($data['error'] as $er) {
				$txt.=$this->messages->message($er)['txt'].'<br>';
			}
			if(!$data['debug'])$data['debug']=array();
			$res['debug']=$data['debug'];
			$res['success']=false;
			if($data['success']===false) {
				$this->logs->save_log($txt.implode(';<br>', $res['debug']));
			}
			$this->db->exec('UPDATE synchronization SET time_start=0, ordersstatuses=?', time());
		}
		$res['logs_n']=$this->f3->get('logs_n');
		$res['remote_receipts']=$this->f3->get('remote_receipts');
		$res['neworders']=$this->neworders;
		$res['txt']=$txt;
		if($this->auto_sinch==1) {
			return $res;
		}
		else {
			echo json_encode($res);
			exit();
		}
	}

	// Клиенты
	// Загрузка клиентов
	function partners_load($time_update=0) {
		if(!is_numeric($time_update)) $time_update=0;
		$res['success']=true;
		$txt='';

		$data=$this->model->partners($time_update); // загружаем клиентов
		if($data['success']===true) {
			// Добавляем клиентов
			$sql=array();
			$val=array();
			foreach ($data['partners'] as $p) {
				$sql[]="INSERT OR REPLACE INTO partners (card, partner_id, group_id, name, email, phone, discount, date_delete, loyalty_type, bonus, bonus_type, bonus_pay, bonus_summ, bonus_bonus, bonus_add_sets, ignore_max_discount, inn) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
				$val[]=array(
					$p['card'],
					$p['partner_id'],
					$p['group_id'],
					$p['name'],
					$p['email'],
					$p['phone'],
					$p['discount'],
					$p['date_delete'],
					$p['loyalty_type'],
					$p['bonus'],
					$p['bonus_type'],
					$p['bonus_pay'],
					$p['bonus_summ'],
					$p['bonus_bonus'],
					$p['bonus_add_sets'],
					$p['ignore_max_discount'],
					$p['inn']
				);
				$time_update=$p['date_update'];
			}
			if(!empty($sql)) {
				if(!$this->db->exec($sql, $val)) {
					$txt.='<br>'.$this->messages->message('db_error')['txt'];
				}
				sleep(1);
			}
			if($txt!='') {
				$this->logs->save_log($txt);
			}

			// Если массив с клиентами был не пустый, то надо продолжить
			if(count($data['partners'])>0) {
				$time_start=time();
				$this->db->exec('UPDATE synchronization SET time_start=?, partners_update=?', array($time_start, $time_update));
				$txt.='<br>'.$this->messages->message('update')['txt'];
				$res['next_step']=$time_start;
			}
			else {
				$txt='<br>'.$this->messages->message('save_successful')['txt'];
				$this->db->exec('UPDATE synchronization SET time_start=?, partners_update=?', array(0, $time_update));
			}
		}
		else { // Если произошла ошибка
			foreach ($data['error'] as $er) {
				$txt.=$this->messages->message($er)['txt'].'<br>';
			}
			if(!$data['debug'])$data['debug']=array();
			$res['debug']=$data['debug'];
			$res['success']=false;
			if($data['success']===false) {
				$this->logs->save_log($txt.implode(';<br>', $res['debug']));
			}
			$this->db->exec('UPDATE synchronization SET time_start=?, partners_update=?', array(0, $time_update));
		}
		$res['txt']=$txt;
		return $res;
	}

	// Загрузка обновленных клиентов
	function partners() {
		// Проверяем не запущена ли уже синхронизация.
		$sinch=$this->db->exec("SELECT * FROM synchronization WHERE time_start=0 OR partners_update<".(time()-600)." LIMIT 1");
		if(!$sinch) {
			$res=array(
				'success'=>false,
				'txt'=>$this->messages->message('sync_is_already_running')['txt']
			);
		}
		else {
			$time_start=microtime(true)+rand(1, 999999)/1000000;
			$this->db->exec('UPDATE synchronization SET time_start=?, partners_timer=?', array($time_start, time()));
			$time_update=$sinch[0]['partners_update'];
			if(!$time_update)$time_update=0;
			$res=$this->partners_load($time_update);
			if($this->f3->get('auto_sinch') && $res['success']) {
				$res['txt']=$this->messages->message('success_partners_synchronization')['txt'];
			}
			$this->db->exec('UPDATE synchronization SET time_start=0');
		}
		$res['logs_n']=$this->f3->get('logs_n');
		$res['remote_receipts']=$this->f3->get('remote_receipts');
		$res['neworders']=$this->neworders;
		if($this->auto_sinch==1) {
			return $res;
		}
		else {
			echo json_encode($res);
			exit();
		}
	}

	// Полная загрузка клиентов
	function partners_all() {
		$time_start=$this->f3->get('GET.time_start'); // Узнаем время запуска синхронизации
		if(!$time_start) $time_start=0; // если время не задано, то это начало синхронизации
		// Проверяем не запущена ли уже синхронизация.
		$sinch=$this->db->exec("SELECT * FROM synchronization LIMIT 1");
		if($sinch[0]['time_start']==$time_start || ($time_start==0 && $sinch[0]['time_start']<time()-600)) {
			if($time_start>0) { // Если синхронизация не только что началась, то время обновления берем из таблицы
				$time_update=$sinch[0]['partners_update'];
			}
			else { // если синхронизация только что началась, то время обновления 0, чтобы получить все товары
				$time_update=0;
			}
			if($time_start==0) { // Если синхронизация только началась, то очищаем таблицы
				$this->db->exec('DELETE FROM partners');
				$this->db->exec('VACUUM');
			}
			$this->db->exec('UPDATE synchronization SET time_start=?', array(time()));
			$res=$this->partners_load($time_update);
		}
		else {
			$mess=$this->messages->message('sync_is_already_running');
			$res['txt']=$mess['txt'];
			$res['success']=false;
		}

		if($res['next_step']) {
			$res['next_step']='/api/partners_all?time_start='.$res['next_step'];
		}
		echo json_encode($res);
		exit();
	}
	//

	// Отдаем чеки
	function tickets($json=true) {
		if(!is_bool($json))$json=true;
		$sinch=$this->db->exec("SELECT * FROM synchronization LIMIT 1");
		if($sinch[0]['time_start']<time()-600) {
			$time_start=round(microtime(true)+rand(1, 9999)/10000, 4);
			$this->db->exec("UPDATE synchronization SET time_start=?", $time_start);
			$time_update=$sinch[0]['tickets_update'];
			if(!$time_update)$time_update=0;
			$receipts=new \Models\Receipts($this->db, $this->f3);
			$tickets=$receipts->select_receipts(array('((r.time>0 AND issued_order>0) OR (r.time>0 AND r.type>=?)) AND r.synch=0', array($this->f3->get('receipt_return'))), array('order'=>'issued_order', 'limit'=>$this->api_data['count']));
			$time_start_control=$this->db->exec("SELECT time_start FROM synchronization LIMIT 1");
			$time_start_control[0]['time_start']=(float)$time_start_control[0]['time_start'];
			if($tickets && $time_start_control[0]['time_start']==$time_start) {
				$res=$this->model->tickets($tickets);
				if(!empty($tickets)) {
					$issued_orders=array_column($tickets, 'issued_order');
					$issued_orders=array_reverse($issued_orders);
					$tickets_update=array_shift($issued_orders);
					if(!$tickets_update) {
						$tickets_update=$time_update;
					}
				}
				else {
					$tickets_update=$time_update;
				}
				if($res['success']===true) {
					$res['txt']=$this->messages->message('save_successful')['txt'];
					$this->db->exec("UPDATE receipts SET synch=1 WHERE id IN (".implode(", ", array_column($tickets, 'id')).")");
					$this->db->exec("UPDATE synchronization SET time_start=0, tickets_update=?", $tickets_update);
				}
				else {
					foreach ($res['error'] as $er) {
						$txt.=$this->messages->message($er)['txt'].'<br>';
					}

					$res['txt']=$txt;
					if($res['success']===false) {
						if(!$res['debug'])$res['debug']=array();
						$this->logs->save_log($txt.implode(';<br>', $res['debug']));
					}
					$res['success']=false;
					/*if($res['noupdate']) {
						$this->db->exec("UPDATE synchronization SET time_start=0");
					}
					else {
						$this->db->exec("UPDATE synchronization SET time_start=0, tickets_update=?", $tickets_update);
					}*/
					$this->db->exec("UPDATE synchronization SET time_start=0");
				}
			}
			elseif($time_start_control[0]['time_start']==$time_start) {
				$res=array(
					'success'=>true,
					'txt'=>$this->messages->message('save_successful')['txt']
				);
				//$this->db->exec("UPDATE synchronization SET time_start=0, tickets_update=?", $time_update);
				$this->db->exec("UPDATE synchronization SET time_start=0");
			}
			else {
				$res=array(
					'success'=>false,
					'txt'=>$this->messages->message('sync_is_already_running')['txt']
				);
			}
			if($this->f3->get('auto_sinch') && $res['success']) {
				$res['txt']=$this->messages->message('success_tickets_synchronization')['txt'];
			}
		}
		else {
			$mess=$this->messages->message('sync_is_already_running');
			$res['txt']=$mess['txt'];
			$res['success']=false;
		}

		if($json) {
			$res['logs_n']=$this->f3->get('logs_n');
			$res['remote_receipts']=$this->f3->get('remote_receipts');
			if($this->auto_sinch==1) {
				return $res;
			}
			else {
				echo json_encode($res);
				exit();
			}
		}
	}

	// Загрузка префиксов для весового штрих-кода и штрих-кода карты клиента
	function barcodes_pr() {
		$res['success']=true;
		$txt='';
		$this->db->exec('UPDATE synchronization SET time_start=?', time());
		$pr=$this->model->barcodes_pr();
		if($pr['success']===true) {
			$sql=array();
			$val=array();
			foreach ($pr['barcodes_pr'] as $name => $value) {
				$sql[]="INSERT OR REPLACE INTO settings (name, value) VALUES (?, ?)";
				$val[]=array($name, $value);
			}
			$r=$this->db->exec($sql, $val);
			if($r!==false) {
				$txt=$this->messages->message('save_successful')['txt'];
			}
			else {
				$txt=$this->messages->message('db_error')['txt'];
			}
		}
		else { // если ответ от сервера не успешный
			$txt='';
			foreach ($pr['error'] as $er) {
				$txt.=$this->messages->message($er)['txt'].'<br>';
			}
			if(!$pr['debug'])$pr['debug']=array();
			$res['debug']=$pr['debug'];
			$res['success']=false;
			if($pr['success']===false) {
				$this->logs->save_log($txt.implode(';<br>', $res['debug']));
			}
		}

		$res['txt']=$txt;
		$this->db->exec('UPDATE synchronization SET time_start=0');

		echo json_encode($res);
		exit();
	}

	// Программы лояльности
	function loyalty() {
		$res['success']=true;
		$txt='';
		$this->db->exec('UPDATE synchronization SET time_start=?', time());
		$loyalty=$this->model->loyalty();
		if($loyalty['success']===true) {
			$loyalty_id='';
			if($loyalty['loyalty']) {
				$loyalty_id=implode(',', array_column($loyalty['loyalty'], 'id'));
			}
			$sql=array();
			$val=array();
			foreach ($loyalty['loyalty'] as $l) {
				$sql[]="INSERT OR REPLACE INTO loyalty (id, date_start, date_end, title, d1, d2, d3, d4, d5, d6, d7, client, partnergroup, data, ignor_maxdiscount, action_type) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
				$val[]=array(
					$l['id'],
					$l['date_start'],
					$l['date_end'],
					$l['title'],
					$l['d1'],
					$l['d2'],
					$l['d3'],
					$l['d4'],
					$l['d5'],
					$l['d6'],
					$l['d7'],
					$l['client'],
					$l['partnergroup'],
					$l['data'],
					$l['ignor_maxdiscount'],
					$l['action_type']
				);
			}
			if($sql) {
				$r=$this->db->exec($sql, $val);
			}
			if($r!==false || empty($sql)) {
				$txt=$this->messages->message('success_loyalty_synchronization')['txt'];
				//Скидки
				if($loyalty['discounts']) {
					$sql="INSERT OR REPLACE INTO discounts (value) VALUES ";
					$val=array();
					foreach ($loyalty['discounts']['discounts'] as $value) {
						if(!empty($val)) $sql.=', ';
						$sql.='(?)';
						$val[]=$value;
					}
				}
				if(!empty($val)) {
					$r=$this->db->exec($sql, $val);
					if($r===false) {
						$txt=$this->messages->message('db_error')['txt'];
					}
				}
			}
			else {
				$txt=$this->messages->message('db_error')['txt'];
			}
			// Удаляем старые акции
			$sql="DELETE FROM `loyalty` WHERE `date_end`<=?";
			if($loyalty_id!='') {
				$sql.=" OR id NOT IN (".$loyalty_id.")";
			}
			else {
				$sql.=" OR id>0";
			}
			$this->db->exec($sql, time());
		}
		else { // если ответ от сервера не успешный
			$txt='';
			foreach ($loyalty['error'] as $er) {
				$txt.=$this->messages->message($er)['txt'].'<br>';
			}
			if(!$loyalty['debug'])$loyalty['debug']=array();
			$res['debug']=$loyalty['debug'];
			$res['success']=false;
			if($loyalty['success']===false) {
				$this->logs->save_log($txt.implode(';<br>', $res['debug']));
			}
		}

		$res['txt']=$txt;
		$this->db->exec('UPDATE synchronization SET time_start=0, loyalty=?', time());
		$res['remote_receipts']=$this->f3->get('remote_receipts');
		if($this->auto_sinch==1) {
			return $res;
		}
		else {
			echo json_encode($res);
			exit();
		}
	}

	// Добавляем документы для фискализации в БД
	function add_remote_receipts($receipts) {
		if(is_array($receipts)) {
			// Проверяем существование чеков
			$exists=array();
			$in='-1';
			$val=array();
			foreach ($receipts as $r) {
				$in.=', ?';
				$val[]=$r['id'];
			}
			$sql="SELECT id FROM `receipts` WHERE `remote` IN (".$in.")";
			$res=$this->db->exec($sql, $val);
			if($res) {
				foreach ($res as $r) {
					$exists[$r['remote']]=$r['id'];
				}
			}

			$add=0;
			foreach ($receipts as $r) {
				if(!isset($exists[$r['remote']])) {
					// Добавляем новый чек
					$sql="INSERT INTO `receipts` (`user_id`, `rm`, `store`, `time`, `sum`, `discount`, `client`, `partner_id`, `remote`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
					$client=$r['other']['phone'];
					if($r['other']['email']) {
						$client=$r['other']['email'];
					}

					$val=array(
						$r['user_id'],
						$this->api_data['rm_id'],
						$this->api_data['store_id'],
						-1,
						$r['sum'],
						0,
						$client,
						$r['partner_id'],
						$r['id']
					);
					$res=$this->db->exec($sql, $val); 
					if($res===false) {
						return array(
							'success'=>false,
							'txt'=>'db_error'
						);
					}
					$receipt_id=$this->db->lastInsertId();

					// Добавляем товары
					if($r['receiptlines']) {
						$sql="INSERT INTO `receiptlines` (`receipt_id`, `product_id`, `product_title`, `price`, `price0`, `vat`, `vat_type`, `count`, `line_discount`, `discount`) VALUES ";
						$val=array();
						foreach ($r['receiptlines'] as $l) {
							if(!empty($val)) $sql.=', ';
							$sql.="(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
							$val[]=$receipt_id;
							$val[]=$l['product_id'];
							$val[]=$l['title'];
							$val[]=$l['price']-($l['price']/100*$l['discount']);
							$val[]=$l['price'];
							$val[]=$l['vat'];
							$val[]=$l['vat_type'];
							$val[]=$l['count'];
							$val[]=$l['discount'];
							$val[]=0;
						}
						$res=$this->db->exec($sql, $val);
						if($res===false) {
							$this->db->exec("DELETE FROM `receipts` WHERE `id`=? LIMIT 1", $receipt_id);
							return array(
								'success'=>false,
								'txt'=>'db_error'
							);
						}
					}
					$add++;
				}
			}
		}

		return array(
			'success'=>true,
			'count'=>$add,
			'txt'=>'successfully_added_fiscalization'
		);
	}

	// Запрашиваем баланс аккаунта
	function balance() {
		$this->db->exec('UPDATE synchronization SET time_start=?', time());
		$res=$this->model->balance();
		if($res['success']===true) {
			$settings=new \Models\Settings($this->f3, $this->db);
			$settings_res=$settings->save_base(array('balance'=>$res['balance'], 'balance_alarm'=>$res['alarm']?1:0));
			if($settings_res['success']) {
				if($res['balance']>0) {
					$txt=$this->messages->message('full_version')['txt'];
				}
				else {
					$txt=$this->messages->message('limited_version')['txt'];
				}
			}
			else {
				$txt=$this->messages->message($settings_res['txt'])['txt'];
			}
		}
		else { // если ответ от сервера не успешный
			$txt='';
			foreach ($res['error'] as $er) {
				$txt.=$this->messages->message($er)['txt'].'<br>';
			}
			if(!$res['debug'])$res['debug']=array();
			$res['success']=false;
			if($res['success']===false) {
				$this->logs->save_log($txt.implode(';<br>', $res['debug']));
			}
		}

		$res['txt']=$txt;
		$this->db->exec('UPDATE synchronization SET time_start=0');
		$res['remote_receipts']=$this->f3->get('remote_receipts');
		if($this->auto_sinch==1) {
			return $res;
		}
		else {
			echo json_encode($res);
			exit();
		}
	}

	// Запрашиваем документы на удаленную фискализацию
	function get_remote_receipts() {
		$res['success']=true;
		$txt='';
		$sinch=$this->db->exec("SELECT * FROM synchronization LIMIT 1");
		$this->db->exec('UPDATE synchronization SET time_start=?', time());

		// Список документов, которые были фискализированны с прошлого раза
		//$r=new \Models\Receipts($this->db, $this->f3);
		//$tickets=$r->success_fiscalization($sinch[0]['fiscalization']);

		$add=0;
		$receipts=$this->model->get_remote_receipts($this->api_data['rm_id']);
		if($receipts['success']===true) {
			// Добавляем в базу полученные чеки
			$res=$this->add_remote_receipts($receipts['receipts']);
			$add=$res['count'];
			$txt=$this->messages->message($res['txt'])['txt'];
		}
		else { // если ответ от сервера не успешный
			$txt='';
			foreach ($receipts['error'] as $er) {
				$txt.=$this->messages->message($er)['txt'].'<br>';
			}
			if(!$receipts['debug'])$receipts['debug']=array();
			$res['debug']=$receipts['debug'];
			$res['success']=false;
			if($receipts['success']===false) {
				$this->logs->save_log($txt.implode(';<br>', $res['debug']));
			}
		}
		$res['logs_n']=$this->f3->get('logs_n');
		$res['remote_receipts']=$this->f3->get('remote_receipts')+$add;
		$res['txt']=$txt;
		$this->db->exec('UPDATE synchronization SET time_start=0, fiscalization=?', microtime(true));

		if($this->auto_sinch==1) {
			return $res;
		}
		else {
			echo json_encode($res);
			exit();
		}
	}

	// синхронизация ошибок синхронизации
	function logs() {
		$sinch=$this->db->exec("SELECT logs FROM synchronization LIMIT 1");
		$this->db->exec('UPDATE synchronization SET time_start=?', time());
		$logs=$this->logs->select_log(array('time>?', $sinch[0]['logs']), array('order'=>'time', 'limit'=>$this->api_data['count']));
		if($logs) {
			$times=array_reverse(array_column($logs, 'time'));
			$res=$this->model->logs($this->api_data['rm_id'], $logs);
			if($res['success']===true) {
				$res['txt']=$this->messages->message('successfully_synchronization_logs')['txt'];
			}
			else {
				$txt='';
				foreach ($res['error'] as $er) {
					$txt.=$this->messages->message($er)['txt'].'<br>';
				}
				if(!$res['debug'])$res['debug']=array();
				$res['success']=false;
				if($res['success']===false) {
					$this->logs->save_log($txt.implode(';<br>', $res['debug']));
				}
				$res['txt']=$txt;
			}
		}
		else {
			$times[0]=time();
			$res['success']=true;
			$res['txt']=$this->messages->message('successfully_synchronization_logs')['txt'];
		}
		if($res['success']==true) {
			$this->db->exec('UPDATE synchronization SET time_start=0, logs=?', $times[0]);
		}
		else {
			$this->db->exec('UPDATE synchronization SET time_start=0');
		}
		$this->logs->delete_log(array('time<?', time()-3600*24*7));
		$res['remote_receipts']=$this->f3->get('remote_receipts');
		$res['neworders']=$this->neworders;
		if($this->auto_sinch==1) {
			return $res;
		}
		else {
			echo json_encode($res);
			exit();
		}
	}

	// Авто синхронизация
	function auto() {
		// Кол-во ошибок синхронизации
		if((int)$this->sets['autonomous']==1) {
			return;
		}
		$logs=$this->logs->select_log(array('read=?', 0));
		$res['logs_n']=count($logs);
		$this->f3->set('logs_n', $res['logs_n']);
		$this->neworders=0;
		$new_orders_res=$this->model->neworderscount();
		if($new_orders_res['success']) {
			$this->neworders=$new_orders_res['count'];
		}

		$sinch=$this->db->exec("SELECT * FROM synchronization WHERE time_start=0 OR time_start<".(time()-600)." LIMIT 1");
		if(!$sinch) {
			$res['success']=false;
			$res['txt']=$this->messages->message('sync_is_already_running')['txt'];
		}
		elseif($sinch[0]['auto_sinch']<0 || $this->sets['autonomous']) {
			return;
		}
		elseif($sinch[0]['auto_sinch']>time()-$this->f3->get('synchronization_timer')*60) {
			$res['success']=false;
			$res['txt']=$this->messages->message('no_synchronization_required')['txt'];
		}
		else {
			$result=array(
				'success'=>true,
				'txt'=>''
			);
			$this->f3->set('auto_sinch', 1);
			$this->auto_sinch=1;
			$res=$this->balance();
			$balance=$res['balance'];
			$balance_alarm=$res['alarm'];

			if($balance<=0) {
				$this->db->exec("UPDATE synchronization SET auto_sinch=?", time());
				echo json_encode($res);
				exit();
			}

			$res=$this->get_remote_receipts();
			if(!$res['success']) {
				$result['success']=false;
				$result['txt'].=$res['txt'].'<br>';
			}

			if($sinch[0]['users_update']<time()-3600) {
				$this->db->exec("UPDATE synchronization SET auto_sinch=?", time());
				$this->users();
			}
			elseif($sinch[0]['ordersstatuses']<time()-3600) {
				$this->db->exec("UPDATE synchronization SET auto_sinch=?", time());
				$this->ordersstatuses();
			}
			elseif($sinch[0]['logs']<time()-3600) {
				$this->db->exec("UPDATE synchronization SET auto_sinch=?", time());
				$this->logs();
			}
			elseif($sinch[0]['loyalty']<time()-3600) {
				$this->db->exec("UPDATE synchronization SET loyalty=?", time());
				$this->loyalty();
			}

			if(!$res['success']) {
				$result['success']=false;
				$result['txt'].=$res['txt'].'<br>';
			}
			
			$res=$this->tickets();
			if(!$res['success']) {
				$result['success']=false;
				$result['txt'].=$res['txt'].'<br>';
			}

			$res=$this->products();

			if(!$res['success']) {
				$result['success']=false;
				$result['txt'].=$res['txt'].'<br>';
			}

			$res=$this->partners();
			if(!$res['success']) {
				$result['success']=false;
				$result['txt'].=$res['txt'].'<br>';
			}

			if($result['success']) {
				$result['txt']=$this->messages->message('successfully_synchronization')['txt'];;
			}
			$this->db->exec("UPDATE synchronization SET auto_sinch=?", time());
			$res=$result;
			$res['balance']=$balance;
			$res['balance_alarm']=$balance_alarm;
		}
		$res['neworders']=$this->neworders;
		// Кол-во чеков для удаленной фискализации
		$res['remote_receipts']=$this->db->exec("SELECT COUNT(*) AS count FROM `receipts` WHERE `remote`>0 AND `time`<0")[0]['count'];
		echo json_encode($res);
		exit();
	}

	function searchsubdomain() {
		echo $this->model->searchsubdomain($this->f3->get('GET.term'));
		exit();
	}

	function getstores() {
		$get=$this->f3->get('GET');
		$res=$this->model->getstores($get);
		$options='';
		if($res['success'] && $res['stores']) {
			foreach($res['stores'] as $s){
				$options.='<option value="'.$s['id'].'"';
				if($this->api_data['store_id']==$s['id']) {
					$options.=' selected="selected" ';
				}
				$options.='>'.$s['title'].'</option>';
			}
		}
		else {
			$res['error'][0]=$this->messages->message($res['error'][0])['txt'];
		}
		$res['options']=$options;
		echo json_encode($res);
		exit();
	}

	function deliveryaction() {
		$url=html_entity_decode(urldecode($this->f3->get('GET.url')));
		$res=$this->model->deliveryaction($url);
		if(!$res['success']) {
			$res['error'][0]=$this->messages->message($res['error'][0])['txt'];
		}
		echo json_encode($res);
		exit();
	}

	function new_version () {
		$res=$this->model->new_version($this->f3->get('site_version'));
		if(!$res['success']) {
			if(!is_array($res['error'])) {
				$res['error']=array($res['error']);
			}
			$res['error'][0]=$this->messages->message($res['error'][0])['txt'];
		}
		echo json_encode($res);
		exit();
	}
}
