<?php

// TODO: waitIfNeeded - check open tables ; facut local; vezi si tbl lunar

namespace App\Cron\Job;

class AppAsyncUpdate extends \App\Cron\Job\Utils\GeneralAbstract
{

	/**
	 * Cronjob category: {system|operational|financial|reporting}
	 * @var string
	 */
	protected $category = 'system';


	/**
	 * {@inheritDoc}
	 * @see \App\Cron\Job\Utils\GeneralAbstract::validateSettings()
	 */
	public function validateSettings(\App\Entity\Messages $msgs, array $fields)
	{

		if ($fields['scheduleOptions']['type']=='interval' ) {
			list($h, $m, $s) = explode(':', $fields['scheduleOptions']['repeatPeriod']);
			$repeatPeriod = $h*3600 + $m*60 + $s;
			if ($repeatPeriod<300) {
				$msgs->addWarningText("The process should not run more often than 2 minutes.", 'type');
			}
			if ($repeatPeriod>7200) {
				$msgs->addWarningText("The process should not run more seldom than 2 hours.", 'type');
			}
		} else {
			$msgs->addWarningText("The process should be set as `multiple times per day`.", 'type');
		}

	}


	/**
	 * {@inheritDoc}
	 * @see \App\Cron\Job\Utils\GeneralAbstract::executeJob()
	 */
	protected function executeJob()
	{

		$db = \DB::getInstance();

		// GET THE LIST OF SQLs ///////////////////////////////////////////////////////////////////

		$queriesListSQL = "SELECT * FROM `updaterAsyncSqls` ORDER BY id ASC";
		$queriesList = $db->GetAll($queriesListSQL);
		if ($db->ErrorNo()) {
			throw new \DBException('Could not get the list of queries ');
		}
		$queriesListCount = count($queriesList);
		if (!$queriesList) {
			$this->logger->idle('No SQLs in the queue. The previous TINA update finished successfully.');
		} else {
			$this->logger->info(sprintf('Found %s SQLs to be executed.', $queriesListCount));
		}


		$solvedSqlsCount = 0;
		// EXECUTE ALL QUERIES ////////////////////////////////////////////////////////////////////
		foreach ($queriesList as $query) {

			$solvedSqlsCount++;

			$this->logger->info(sprintf('Start executing [%s] %s/%s (id:%s) on table/entity `%s`.', $query['type'], $solvedSqlsCount, $queriesListCount, $query['id'], $query['dbTable'] ));

			// type = simpleSql / monthSql - execute query
			if ($query['type']=='simpleSql' or $query['type']=='monthSql') {
				$db->Execute($query['query']);
				if ($db->ErrorNo()) {
					if ($query['ignoreErrors']) {
						$this->logger->info( sprintf( 'Found an SQL (#%s) that failed during execution but it was marked to ignore errors. SQL: %s ; Error message: %s.', $query['id'], $query['query'], $db->ErrorMsg() ) );
					} else {
						$this->logger->critical(sprintf('Failed to execute the SQL #%s on table `%s`. SQL: %s ; Error message: %s.', $query['id'], $query['dbTable'], $query['query'], $db->ErrorMsg()));
						$this->logger->critical('The cron will stop but there is a high chance you will get the same error during next execution - this error should be thoroughly analyzed and fixed.');
						\Log::getInstance()->dbError(sprintf('Failed to execute async SQL #%s.', $query['id']));
						return ;
					}
				} else {
					$this->logger->success(sprintf('Successfully executed the SQL #%s on table `%s`.', $query['id'], $query['dbTable']));
				}
			}
			// type = rdSync
			elseif ($query['type']=='rdSync') {

				\DB::startTransaction();
				$className = "\\App\\ReportsData\\ChangesQueue\\Entity\\" . $query['dbTable'];
				if (!class_exists($className)) {
					$this->logger->critical( sprintf('Failed to execute the RD resync on %s - invalid entity name.', $query['dbTable']) );
					\DB::rollbackTransaction();
					return ;
				}
				$resyncObj = new $className();
				$resyncObj->resync();
				\DB::commitTransaction();
				$this->logger->success(sprintf('Successfully executed RD synchronization (#%s) on `%s`.', $query['id'], $query['dbTable']));

			}

			// eliminate the SQL from the queue
			$removeQuerySQL = "DELETE FROM `updaterAsyncSqls` WHERE id=?";
			$db->Execute($removeQuerySQL, [ $query['id'] ]);

			if ($db->ErrorNo()) {
				$this->logger->critical(sprintf('Failed to remove SQL #%s from the queue. The cron will stop but there is a high chance you will get the same error during the next execution - this error should be thoroughly analyzed and fixed.', $query['id']));
				return ;
			}

			$this->updateStatus(['progress'=>$solvedSqlsCount/$queriesListCount]);

		}

		// display final success message
		if ($queriesList) {
			$this->logger->info(sprintf('Successfully executed %s SQLs.', $queriesListCount));
		}

	}

}

