<?php
/**
* Classe Database.class.php
* @filesource
* @autor		Kenio de Souza
* @copyright	Copyright 2024 - Souza Consultoria Tecnológica
* @package		vendor
* @subpackage	model
* @version		1.0
* @date			10/08/2024
*/


/** Defino o local onde esta a classe */
namespace vendor\model;

class Database
{
	/** Declaro as vaiavéis da classe */
	private $connection = null;
	private $sql = null;
	private $stmt = null;
	private $start = null;
	private $max = null;
	private $limit = null;
	private $dbId = null;
	private $stationId = null;
	private $description = null;
	private $capacity = null;
	private $used = null;
	private $available = null;
	private $availablePercentage = null;
	private $registrationDate = null;
	private $field = null;
	private $lastId = null;
	private $errors = [];
	private $info = null;
	private $clientId = null;
	private $fileSize = null;
	private $lastModified = null;
	private $dbAccessible = null;
	private $dbPartition = null;

	/** Construtor da classe */
	function __construct()
	{
		/** Cria o objeto de conexão com o banco de dados */
		$this->connection = new Mysql();
	}

	/** Carrega os campos de uma tabela */
	public function Describe()
	{

		/** Consulta SQL */
		$this->sql = "describe db";

		/** Preparo o SQL para execução */
		$this->stmt = $this->connection->connect()->prepare($this->sql);

		/** Executo o SQL */
		$this->stmt->execute();

		/** Retorno o resultado */
		$this->field = $this->stmt->fetchAll(\PDO::FETCH_OBJ);

		/** Declara o objeto */
		$resultDescribe = new \stdClass();
		$Field = '';

		/** Lista os campos da tabela para objetos */
		foreach($this->field as $UsersKey => $Result){

			/** Pega o nome do Field/Campo */
			$Field = $Result->Field;

			/** Carrega os objetos como null */
			$resultDescribe->$Field = null;

		}

		/** Retorna os campos declarados como vazios */
		return $resultDescribe;

	}

	/** Lista os registros do banco de dados com limitação */
	public function Get(int $dbId)
	{

		/** Parametros de entrada */
		$this->dbId = $dbId;

		/** Consulta SQL */
		$this->sql = 'select * from db  
					  where db_id = :db_id';

		/** Preparo o SQL para execução */
		$this->stmt = $this->connection->connect()->prepare($this->sql);

		/** Preencho os parâmetros do SQL */
		$this->stmt->bindParam(':db_id', $this->dbId);

		/** Executo o SQL */
		$this->stmt->execute();

		/** Retorno o resultado */
		return $this->stmt->fetchObject();

	}
	
	/** Insere um novo registro no banco */
	public function Save(int $clientId,
	                     ? string $fileSize, 
						 ? string $lastModified, 
						 ? string $dbAccessible,
						 ? string $dbPartition)
	{


		/** Parametros */
		$this->clientId     = $clientId;
		$this->fileSize     = $fileSize;
		$this->lastModified = $lastModified;
		$this->dbAccessible = $dbAccessible;
		$this->dbPartition  = $dbPartition;

		/** Consulta SQL */
		$this->sql = 'insert into db(client_id,
		                             file_size, 
									 last_modified, 
									 db_accessible,
									 db_partition
						   ) values (:client_id,
							         :file_size, 
								     :last_modified,
								     :db_accessible,
									 :db_partition)';

		try{

			/** Preparo o sql para receber os valores */
			$this->stmt = $this->connection->connect()->prepare($this->sql);
			
			/** Inicia a transação */
			$this->connection->connect()->beginTransaction();					

			/** Preencho os parâmetros do SQL */
			$this->stmt->bindParam(':client_id', $this->clientId);
			$this->stmt->bindParam(':file_size', $this->fileSize);
			$this->stmt->bindParam(':last_modified', $this->lastModified);
			$this->stmt->bindParam(':db_accessible', $this->dbAccessible);
			$this->stmt->bindParam(':db_partition', $this->dbPartition);

			/** Executo o SQL */
			$this->stmt->execute();		

			/** Confirma a transação */
			$this->connection->connect()->commit();
			return true;			

		} catch (\Exception $exception) {

			/** Desfaz a transação */
			$this->connection->connect()->rollback();

            /** Informo */
            throw new InvalidArgumentException($exception->getMessage(), 0);
		}		
					
	}

	/** Deleta um determinado registro no banco de dados */
	function Delete(int $clientId)
	{
		/** Parametros de entrada */
		$this->clientId = $clientId;

		/** Consulta SQL */
		$this->sql = 'delete from db
					  where  client_id = :client_id';


		try {					  

			/** Preparo o sql para receber os valores */
			$this->stmt = $this->connection->connect()->prepare($this->sql);

			/** Inicia a transação */
			$this->connection->connect()->beginTransaction();

			/** Preencho os parâmetros do SQL */
			$this->stmt->bindParam('client_id', $this->clientId);

			/** Executo o SQL */
			$this->stmt->execute();

			/** Confirma a transação */
			$this->connection->connect()->commit();
			return true;

		} catch (\Exception $exception) {

			/** Desfaz a transação */
			$this->connection->connect()->rollback();

            /** Informo */
            throw new InvalidArgumentException($exception->getMessage(), 0);
		}
	}	

	/** Define o Último ID inserido */
	public function setId($lastId) : void
	{
		$this->lastId = $lastId;
	}

	/** Recupera o Último ID inserido */
	public function getId(): ? int
	{
		return (int)$this->lastId;
	}	

	/** Retorna os erros ocorridos */
	public function getErrors(): ? string
	{

		/** Verifico se deve informar os erros */
		if (count($this->errors)) {

	   		/** Verifica a quantidade de erros para informar a legenda */
	   		$this->info = count($this->errors) > 1 ? '<center>Os seguintes erros foram encontrados</center>' : '<center>O seguinte erro foi encontrado</center>';

	    	/** Lista os erros  */
	    	foreach ($this->errors as $keyError => $error) {

	        	/** Monto a mensagem de erro */
	        	$this->info .= '</br>' . ($keyError + 1) . ' - ' . $error;

    		}

    		/** Retorno os erros encontrados */
    		return (string)$this->info;

		} else {

    		return false;

		}

	}	

	/** Fecha uma conexão aberta anteriormente com o banco de dados */
	function __destruct()
	{
		$this->connection = null;
    }
}
