<?php

	ini_set('display_errors', '1');
	ini_set('display_startup_errors', '1');
	error_reporting(E_ALL);
	class ATAjax {
		public function response() {
			$res = [
				'code' => 0,
				'message' => 'Something error'
			];
			$action = $_POST['_a'];
			try {
				switch ($action) {
					case "test_connection_database":
						$res = $this->testConnectionDatabase();
						break;
					case "install_package":
						$res = $this->installPackage();
						break;
					case "get_db_index_after_install_package":
						$res = $this->getDatabaseIndexAfterInstall();
						break;
					case "remove_install_files":
						$res = $this->removeInstallFiles();
						break;
					case "import_database":
						$res = $this->importDatabase();
						break;
				}
			} catch (Exception $e) {
				$res['message'] = $e->getMessage();
			}
			
			return json_encode($res);
		}
		
		private function removeInstallFiles() {
			$folder_installer = __DIR__;
			$root_path = dirname($folder_installer);
			$file_installer = $root_path . '/installer.php';
			$file_context = $root_path . "/coremigrate_context.json";
			$file_backup = $root_path . "/backup.mysql";
			$file_backup_pointer = $root_path . "/backup.mysql_filepointer";
			$file_backup_error = $root_path . "/backup.mysql_error";
			$package_path = $_POST['package_path'];
			
			if ($root_path != dirname($package_path)) {
				return [
					'code' => 0,
					'message' => 'Package path is invalid'
				];
			}
			
			if (file_exists($folder_installer)) {
				exec('rm -rf '.escapeshellarg($folder_installer));
			}
			
			if (file_exists($file_installer)) {
				unlink($file_installer);
			}
			
			if (file_exists($file_context)) {
				unlink($file_context);
			}
			
			if (file_exists($file_backup)) {
				unlink($file_backup);
			}
			
			if (file_exists($package_path) && basename(dirname($package_path)) == basename(dirname($folder_installer))) {
				unlink($package_path);
			}
			
			if (file_exists($file_backup_pointer)) {
				unlink($file_backup_pointer);
			}
			
			if (file_exists($file_backup_error)) {
				unlink($file_backup_error);
			}
			
			return [
				'code' => 1,
				'message' => 'Removed install files successfully'
			];
		}
		
		private function installPackage() {
			$extract_path = $_POST['extract_path'];
			$package_path = $_POST['package_path'];
			if (!is_file($package_path)) {
				return [
					'code' => 0,
					'message' => 'Cannot found package file'
				];
			}
			if (!(file_exists($extract_path) && is_dir($extract_path))) {
				return [
					'code' => 0,
					'message' => 'Extract path is invalid'
				];
			}
			
			if (!isset($_POST['site_url'])) {
				return [
					'code' => 0,
					'message' => 'Site url is required'
				];
			}
			
			if (filter_var($_POST['site_url'], FILTER_VALIDATE_URL) === FALSE) {
				return [
					'code' => 0,
					'message' => 'Site url is invalid'
				];
			}
			
			$context = file_get_contents("./coremigrate_context.json");
			$context = json_decode($context, true);
			$this->_context = $context;
			
			
			$package_zip = new ZipArchive;
			if ($package_zip->open($package_path) === FALSE) {
				return [
					'code' => 0,
					'message' => 'Cannot unzip package'
				];
			}
			$package_zip->extractTo($extract_path);
			$package_zip->close();
			
			$this->applyDomainNewShop($extract_path, $context);
			
			if (file_exists($extract_path . "/backup.mysql_filepointer")) {
				unlink($extract_path."/backup.mysql_filepointer");
			}
			if (file_exists($extract_path . "/backup.mysql_error")) {
				unlink($extract_path."/backup.mysql_error");
			}
			
			return [
				'code' => 1,
				'message' => 'Unzip package successfully, Please wait for database import'
			];
		}
		
		private function getDatabaseIndexAfterInstall() {
			$context = file_get_contents("./coremigrate_context.json");
			$context = json_decode($context, true);
			$this->_context = $context;
			
			$database_host = $_POST['database_host'];
			$database_port = $_POST['database_port'];
			$database_database = $_POST['database_database'];
			$database_user = $_POST['database_user'];
			$database_password = $_POST['database_password'];
			$conn = new PDO("mysql:host=$database_host; dbname=$database_database;port=$database_port;", $database_user, $database_password);
			
			$table_prefix = $context['database_information']['prefix'];
			$sql = "SELECT COUNT(`id_product`) FROM `{$table_prefix}product` ";
			$stmt = $conn->prepare($sql);
			$stmt->execute();
			$total_product = $stmt->fetchColumn();
			
			$sql = "SELECT COUNT(`id_order`) FROM `{$table_prefix}orders` ";
			$stmt = $conn->prepare($sql);
			$stmt->execute();
			$total_order = $stmt->fetchColumn();
			
			$sql = "SELECT COUNT(`id_module`) FROM `{$table_prefix}module` ";
			$stmt = $conn->prepare($sql);
			$stmt->execute();
			$total_module = $stmt->fetchColumn();
			
			$sql = "SELECT COUNT(`id_image_type`) FROM `{$table_prefix}image_type` ";
			$stmt = $conn->prepare($sql);
			$stmt->execute();
			$total_image_type = $stmt->fetchColumn();
			
			$sql = "SELECT COUNT(`id_image`) FROM `{$table_prefix}image` ";
			$stmt = $conn->prepare($sql);
			$stmt->execute();
			$total_image = $stmt->fetchColumn();
			
			if ($_POST['new_admin_account'] != '' && $_POST['new_admin_account_password'] != '') {
				$sql = "SELECT * FROM `{$table_prefix}employee` WHERE id_profile = 1 ORDER BY id_employee ASC";
				$stmt = $conn->prepare($sql);
				$stmt->execute();
				$employee_super_admin = $stmt->fetch(PDO::FETCH_ASSOC);
				
				$new_employee = [
					'id_profile' => $employee_super_admin['id_profile'],
					'lastname' => 'SuperAdmin',
					'firstname' => "Migrate",
					'email' => $_POST['new_admin_account'],
					'passwd' => md5("{$context['cookie_key']}{$_POST['new_admin_account_password']}"),
					'last_passwd_gen' => date('Y-m-d', time()),
					'stats_date_from' => date('Y-m-d', time()),
					'stats_date_to' => date('Y-m-d', time()),
					'stats_compare_option' => 1,
					'bo_theme' => $employee_super_admin['bo_theme'],
					'default_tab' => $employee_super_admin['default_tab'],
					'bo_menu' => $employee_super_admin['bo_menu'],
					'active' => 1,
					'id_lang' => $employee_super_admin['id_lang']
				];
				$sql = "INSERT INTO `{$table_prefix}employee` (id_profile, id_lang, lastname, firstname, email, passwd, last_passwd_gen, stats_date_from,
				stats_date_to, stats_compare_option, bo_theme, default_tab, bo_menu, active)
				VALUES (:id_profile, :id_lang, :lastname, :firstname, :email, :passwd, :last_passwd_gen, :stats_date_from,
				:stats_date_to, :stats_compare_option, :bo_theme, :default_tab, :bo_menu, :active)";
				$stmt = $conn->prepare($sql);
				$stmt->bindParam(':id_profile', $new_employee['id_profile'], PDO::PARAM_INT);
				$stmt->bindParam(':id_lang', $new_employee['id_lang'], PDO::PARAM_INT);
				$stmt->bindParam(':lastname', $new_employee['lastname'], PDO::PARAM_STR);
				$stmt->bindParam(':firstname', $new_employee['firstname'], PDO::PARAM_STR);
				$stmt->bindParam(':email', $new_employee['email'], PDO::PARAM_STR);
				$stmt->bindParam(':passwd', $new_employee['passwd'], PDO::PARAM_STR);
				$stmt->bindParam(':last_passwd_gen', $new_employee['last_passwd_gen'], PDO::PARAM_STR);
				$stmt->bindParam(':stats_date_from', $new_employee['stats_date_from'], PDO::PARAM_STR);
				$stmt->bindParam(':stats_date_to', $new_employee['stats_date_to'], PDO::PARAM_STR);
				$stmt->bindParam(':stats_compare_option', $new_employee['stats_compare_option'], PDO::PARAM_STR);
				$stmt->bindParam(':bo_theme', $new_employee['bo_theme'], PDO::PARAM_STR);
				$stmt->bindParam(':default_tab', $new_employee['default_tab'], PDO::PARAM_STR);
				$stmt->bindParam(':bo_menu', $new_employee['bo_menu'], PDO::PARAM_STR);
				$stmt->bindParam(':active', $new_employee['active'], PDO::PARAM_INT);
				$res = $stmt->execute();
				if (!$res) {
					return [
						'code' => 0,
						'msg' => 'Cannot create new account'
					];
				}
			}
			
			return [
				'code' => 1,
				'msg' => 'Get data successfully',
				'data' => [
					'total_product' => $total_product,
					'total_order' => $total_order,
					'total_module' => $total_module,
					'total_image' => $total_image + ($total_image * $total_image_type)
				]
			];
		}
		
		private function applyDomainNewShop($extract_path, $context) {
			$replace_files = [
				$extract_path . "/.htaccess",
				$extract_path . "/robots.txt",
				$extract_path . "/mails/en/order_conf.html",
				$extract_path . "/mails/es/order_conf.html",
				$extract_path . "/mails/fr/order_conf.html",
				$extract_path . "/mails/it/order_conf.html",
				$extract_path . "/modules/ps_emailalerts/mails/en/return_slip.html",
				$extract_path . "/modules/ps_emailalerts/mails/es/return_slip.html",
				$extract_path . "/modules/ps_emailalerts/mails/it/return_slip.html",
				$extract_path . "/modules/ps_emailalerts/mails/fr/return_slip.html",
				$extract_path . "/config/themes/classic/shop1.json",
			];
			$site_url = $_POST['site_url'];
			$parsed_url = parse_url($site_url);
			$path = $parsed_url['path'];
			$this->_site_host = $parsed_url['host'];
			$path = str_replace("/", "", $path);
			$this->_site_path = $path;
			foreach ($context['shop_domains'] as $key => $domains) {
				foreach ($domains as $domain) {
					foreach ($replace_files as $file) {
						if (!is_file($file) || !file_exists($file)) {
							continue;
						}
						$content_file = @file_get_contents($file);
						$domain['physical'] = str_replace("/", "", $domain['physical']);
						$content_file = str_replace($domain['physical'], $path, $content_file);
						$content_file = str_replace($key, $this->_site_host, $content_file);
						@file_put_contents($file, $content_file);
					}
				}
			}
			
			$database_information = $context['database_information'];
			if (file_exists($extract_path . "/app/config/parameters.php")) {
				$file_content = @file_get_contents($extract_path . "/app/config/parameters.php");
				$file_content = str_replace($database_information['name'], $_POST['database_database'], $file_content);
				$file_content = str_replace($database_information['user'], $_POST['database_user'], $file_content);
				$file_content = str_replace($database_information['password'], $_POST['database_password'], $file_content);
				@file_put_contents($extract_path . "/app/config/parameters.php", $file_content);
			}
		}
		
		private function importDatabase() {
			$context = file_get_contents("./coremigrate_context.json");
			$context = json_decode($context, true);
			$this->_context = $context;
			$extract_path = $_POST['extract_path'];
			$database_host = $_POST['database_host'];
			$database_port = $_POST['database_port'];
			$database_database = $_POST['database_database'];
			$database_user = $_POST['database_user'];
			$database_password = $_POST['database_password'];
			$database_charset = $_POST['database_charset'];
			$database_collation = $_POST['database_collation'];
			
			if (!is_file($extract_path . "/backup.mysql")) {
				return [
					'code' => 0,
					'message' => 'Cannot found file mysql to install database'
				];
			}
			
			if ($database_charset == '') {
				$database_charset = 'utf8mb4';
			}
			if ($database_collation == '') {
				$database_collation = 'utf8mb4_unicode_ci';
			}
			
			return $this->recursiveImportMysql(
				$extract_path,
				$database_host,
				$database_database,
				$database_user,
				$database_password,
				$database_port,
				$database_charset,
				$database_collation
			);
		}
		
		private function recursiveImportMysql(
			$extract_path,
			$host,
			$database,
			$user,
			$password,
			$port,
			$charset = 'utf8mb4',
			$collation = 'utf8mb4_unicode_ci'
		) {
			$site_url = $_POST['site_url'];
			$parsed_url = parse_url($site_url);
			$path = $parsed_url['path'];
			$this->_site_host = $parsed_url['host'];
			$path = str_replace("/", "", $path);
			$this->_site_path = $path;
			
			/* PDO connection start */
			$options = [
				PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
				PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
				PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES '.$charset.' COLLATE '.$collation.' ',
			];
			
			$conn = new PDO("mysql:host=$host; dbname=$database;port=$port;charset=$charset", $user, $password, $options);
			$conn->exec("/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;");
			$conn->exec("/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;");
			$conn->exec("/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;");
			$conn->exec("/*!40101 SET NAMES utf8mb4 */;");
			$conn->exec("/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;");
			$conn->exec("/*!40103 SET TIME_ZONE='+00:00' */;");
			$conn->exec("/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;");
			$conn->exec("/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;");
			$conn->exec("/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;");
			$conn->exec("/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;");
			$conn->exec("/*!40101 SET @saved_cs_client     = @@character_set_client */;");
			$conn->exec("/*!40101 SET character_set_client = utf8 */;");
			
			/* PDO connection end */
			$file_sql = $extract_path . "/backup.mysql";
			$max_run_time = 8;
			$deadline = time()+$max_run_time;
			$progress_filename = $file_sql.'_filepointer'; // tmp file for progress
			$error_filename = $file_sql.'_error'; // tmp file for error
			if (!($fp = fopen($file_sql, 'r'))) {
				if (file_exists($extract_path . "/backup.mysql_filepointer")) {
					unlink($extract_path . "/backup.mysql_filepointer");
				}
				return [
					'code' => 0,
					'message' => 'failed to open file sql'
				];
			}
			if(file_exists($error_filename)){
				return [
					'code' => 0,
					'message' => 'previous error:' . file_get_contents($error_filename)
				];
			}
			
			$file_position = 0;
			if(file_exists($progress_filename)){
				$file_position = file_get_contents($progress_filename);
				fseek($fp, $file_position);
			}
			$queryCount = 0;
			$query = '';
			while($deadline>time() AND ($line=fgets($fp, 1024000))){
				if(substr($line,0,2)=='--' OR trim($line)==''){
					continue;
				}
				$query .= $line;
				if( substr(trim($query),-1)==';' ){
					$igweze_prep= $conn->prepare($query);
					if(!($igweze_prep->execute())){
						$error = 'Error performing query \'<strong>' . $query . '\': ' . print_r($conn->errorInfo());
						file_put_contents($error_filename, $error."\n");
						break;
					}
					$query = '';
					file_put_contents($progress_filename, ftell($fp)); // save the current file position for
					$queryCount++;
				}
			}
			
			if (feof($fp)) {
				$this->updateDatabase($conn);
				return [
					'code' => 1,
					'message' => 'Import database successfully'
				];
			}
			
			return [
				'code' => 1,
				'message' => 'Imported ' .ftell($fp).'/'.filesize($file_sql).' '.(round(ftell($fp)/filesize($file_sql), 2)*100).'%',
				'continue' => true
			];
		}
		
		private function updateDatabase($conn) {
			$old_physical_uris = [];
			foreach ($this->_context['shop_domains'] as $key => $shop_domains) {
				foreach ($shop_domains as $domain) {
					$old_physical_uris[] = $domain['physical'];
				}
			}
			$sql = "UPDATE {$this->_context['database_information']['prefix']}shop_url SET physical_uri = '/{$this->_site_path}/' ";
			if (count($old_physical_uris) > 0) {
				$keywords_imploded = implode("','",$old_physical_uris);
				$sql .= "WHERE physical_uri IN ('$keywords_imploded')";
			}
			$stmt = $conn->prepare($sql);
			$stmt->execute();
		}
		
		private function testConnectionDatabase() {
			$host = $_POST['db_cf_host'];
			$port = $_POST['db_cf_host_port'];
			$database = $_POST['db_cf_database'];
			$user = $_POST['db_cf_user'];
			$password = $_POST['db_cf_password'];
			
			if ($host == '') {
				return [
					'code' => 0,
					'message' => 'Host is invalid'
				];
			}
			if ($port == '') {
				return [
					'code' => 0,
					'message' => 'Port is invalid'
				];
			}
			if ($database == '') {
				return [
					'code' => 0,
					'message' => 'Database is invalid'
				];
			}
			if ($user == '') {
				return [
					'code' => 0,
					'message' => 'User is invalid'
				];
			}
			if ($password == '') {
				return [
					'code' => 0,
					'message' => 'Password is invalid'
				];
			}
			
			$mysqli = new mysqli($host, $user, $password, $database, $port);
			if ($mysqli->connect_errno) {
				return [
					'code' => 0,
					'message' => "Failed to connect to MySQL: " . $mysqli->connect_error
				];
			}
			return [
				'code' => 1,
				'message' => 'Connect database successfully'
			];
		}
	}
?>