<?php

namespace App\Utils\EmailBox;

class Imap extends GeneralAbstract
{

	/**
	 * The PhpImap lib object.
	 * @var \PhpImap\Mailbox
	 */
	protected \PhpImap\Mailbox $mailbox;

	/**
	 * Temporary directory for attachments.
	 * @var string
	 */
	protected string $tempDir;


	/**
	 * Loads configured account credentials from $CFG['loadEmailBookings']['accountsList'].
	 * Validates the account code and the fact that it's active.
	 * @param string $accountName
	 */
	public function loadAccountCredentialsFromConfigs(string $accountName) :void
	{

		$CFG = \Engine\Loader_Cfg::getInstance()->getGlobal();

		if (!key_exists($accountName, $CFG['loadEmailBookings']['accountsList'])) {
			throw new Exception("Invalid account name `{$accountName}` to load IMAP credentials.");
		}

		$accountConfigs = $CFG['loadEmailBookings']['accountsList'][$accountName];

		// check if account is active
		if (!$accountConfigs['active']) {
			throw new Exception("IMAP account name `{$accountName}` is disabled.");
		}

		// load credentials
		$this->username = $accountConfigs['username'];
		$this->password = $accountConfigs['password'];

	}

	/**
	 * Returns the connection path - for ex. for Gmail it's: {imap.gmail.com:993/imap/ssl}INBOX.
	 * @return string
	 */
	protected function getConnectionPath() :string
	{

		$path = '{' . $this->domain;

		if ($this->port) {
			$path .= ":" . $this->port;
		}

		$path .= "/imap/ssl}" . $this->dir;

		return $path;

	}

	/**
	 * Connects to IMAP mailbox.
	 */
	public function connect() :void
	{
		if (!$this->username or !$this->password) {
			throw new Exception('The credentials (username/password) were not set when trying to connect using IMAP.');
		}
		if (isset($this->mailbox)) {
			throw new Exception('Cannot call ' . __METHOD__ . ' more than once.');
		}

		// determine the temp dir to store the emails
		$CFG = \Engine\Loader_Cfg::getInstance()->getGlobal();
		$this->tempDir = APP_REAL_PATH . $CFG['paths']['temporary']. '/emailBox';
		// create temp dir if not already created
		if (!\Engine\Dir::check($this->tempDir)) {
			\Engine\Dir::create($this->tempDir);
		}

		$this->mailbox = new \PhpImap\Mailbox(
			$this->getConnectionPath(),
			$this->username,
			$this->password,
			$this->tempDir, // Directory, where attachments will be saved (optional)
			$this->serverEncoding, // Server encoding (optional) - by default it's  probably UTF-8
			true, // Trim leading/ending whitespaces of IMAP path (optional)
			false // Attachment filename mode (optional; false = random filename; true = original filename)
		);

	}

	/**
	 * Disconnects form IMAP mailbox.
	 */
	public function disconnect() :void
	{
		if (!isset($this->mailbox)) {
			throw new Exception('Cannot call ' . __METHOD__ . ' as the connection was not executed or successful.');
		}

		$this->mailbox->disconnect();

		// Clean up temporary attachment files
		$this->cleanupTempFiles();
	}

	/**
	 * Cleans up temporary attachment files from the temp directory.
	 */
	protected function cleanupTempFiles() :void
	{
		\Engine\Dir::deleteContents($this->tempDir);
	}


	public function search(string $searchString) :array
	{

		try {

			return  $this->mailbox->searchMailbox($searchString);

		} catch(\PhpImap\Exceptions\ConnectionException $ex) {

			throw new Exception( 'IMAP connection failed: ' . implode(', ', $ex->getErrors('all')) );

		}

	}


	public function getMail(string $idMail, bool $markAsSeen) :\PhpImap\IncomingMail
	{
		return $this->mailbox->getMail($idMail, $markAsSeen);
	}

}
