<?php
/**
 * ownCloud
 *
 * @author Tom Needham <tom@owncloud.com>
 * @author Michael Barz <mbarz@owncloud.com>
 * @copyright (C) 2018 ownCloud GmbH
 * @license ownCloud Commercial License
 *
 * This code is covered by the ownCloud Commercial License.
 *
 * You should have received a copy of the ownCloud Commercial License
 * along with this program. If not, see
 * <https://owncloud.com/licenses/owncloud-commercial/>.
 *
 */

namespace OCA\Files_Lifecycle;

use Doctrine\DBAL\Platforms\MySQLPlatform;
use Doctrine\DBAL\Platforms\OraclePlatform;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use OCA\Files_Lifecycle\Dav\ArchivePlugin;
use OCA\Files_Lifecycle\Policy\PolicyManager;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\Files\StorageNotAvailableException;
use OCP\IDBConnection;
use OCP\IUser;

/**
 * Class ExpireQuery
 *
 * @package OCA\Files_Lifecycle
 */
class ExpireQuery {
	public const MAIN_SQL = <<<EOS
SELECT f.*, p.`propertyvalue` FROM `*PREFIX*filecache` f
  LEFT JOIN `*PREFIX*properties` p ON p.`fileid` = f.`fileid` AND p.`propertyname` = ?
  WHERE p.`propertyvalue` IS NOT NULL AND f.`storage` = ?
EOS;

	public const SQL_UTIME = ' AND CAST(p.`propertyvalue` AS DATETIME) < CAST(? AS DATETIME)';

	public const PGSQL_UTIME = ' AND CAST(p.`propertyvalue` AS timestamp) < CAST(? AS timestamp)';

	public const OCI_SQL_UTIME = ' AND p.`propertyvalue` < ?';

	/**
	 * @var IRootFolder
	 */
	protected $rootFolder;

	/**
	 * @var IDBConnection
	 */
	protected $db;

	/** @var PolicyManager */
	protected $policyManager;

	/**
	 * ExpireQuery constructor.
	 *
	 * @param IRootFolder $rootFolder
	 * @param IDBConnection $connection
	 * @param PolicyManager $policyManager
	 *
	 */
	public function __construct(
		IRootFolder $rootFolder,
		IDBConnection $connection,
		PolicyManager $policyManager
	) {
		$this->rootFolder = $rootFolder;
		$this->db = $connection;
		$this->policyManager = $policyManager;
	}

	/**
	 * Get Files to expire for User
	 *
	 * @param IUser $user
	 *
	 * @return \Generator
	 *
	 * @throws NotFoundException
	 * @throws StorageNotAvailableException
	 * @throws \Exception
	 *
	 */
	public function getUserFilesForExpiry(IUser $user) {
		try {
			$storage = $this->rootFolder->get(
				$user->getUID() . '/archive'
			)->getStorage();
		} catch (NotFoundException $e) {
			return;
		}
		$storageId = $storage->getCache()->getNumericStorageId();
		$policy = $this->policyManager->getConfiguredPolicy();
		$expirePeriod = $policy->getExpirePeriod();

		$now = new \DateTime();
		$expirationTime = $now->sub(
			\DateInterval::createFromDateString(
				$expirePeriod . ' days'
			)
		);

		$params = [
			ArchivePlugin::ARCHIVED_TIME,
			(string) $storageId,
			$expirationTime->format(\DateTime::ATOM)
		];
		$query = self::MAIN_SQL;
		if ($this->db->getDatabasePlatform() instanceof PostgreSQLPlatform) {
			$query .= self::PGSQL_UTIME;
		} elseif ($this->db->getDatabasePlatform() instanceof MySQLPlatform) {
			$query .= self::SQL_UTIME;
		} elseif ($this->db->getDatabasePlatform() instanceof OraclePlatform) {
			$query .= self::OCI_SQL_UTIME;
		} else {
			$query .= self::OCI_SQL_UTIME;
		}

		$statement = $this->db->executeQuery($query, $params);
		while ($row = $statement->fetchAssociative()) {
			yield $row;
		}

		$statement->free();
	}
}
