<?php

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


/** Defino o local onde esta a classe */

namespace vendor\model;

class Log
{

	/** Configurações de acess a API do Telegram */
	private $botToken = null;
	private $chatId = null;

	/** Declaro as vaiavéis da classe */
	private $connection = null;
	private $sql = null;
	private $stmt = null;
	private $start = null;
	private $end = null;
	private $max = null;
	private $limit = null;
	private $logId = null;
	private $clientId = null;
	private $datePost = null;
	private $file = null;
	private $errors = [];
	private $lastId = null;
	private $field = null;
	private $stationId = null;
	private $message = null;
	private $url = null;
	private $postFields = null;
	private $response = null;
	private $cns = null;
	private $dir = null;
	private $info = null;

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

		/** Configurações de acess a API do Telegram */
		$this->botToken = '7406234299:AAG7CvM0g4Hd1mNSGiJ6MMWtWUsTeQUXQU4';
		//$this->chatId = '5412487603';
		$this->chatId = "-1002192374760";
	}

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

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

		/** 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 $clientId)
	{

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

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

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

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

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

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

	/** Lista todos os egistros do banco com ou sem paginação*/
	public function All(int $clientId, $stationId)
	{

		/** Parametros de entrada */
		$this->clientId = $clientId;
		$this->stationId = $stationId;

		/** Consulta SQL */
		$this->sql = 'select * from log 
		              where client_id = :client_id 
					  and station_id = :station_id
					  order by log_id desc';

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

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

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

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

	/** Conta a quantidades de registros */
	public function Count()
	{
		/** Consulta SQL */
		$this->sql = 'select count(client_id) as qtde
					  from log ';

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

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

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

	/** Insere um novo registro no banco */
	public function Save(int $clientId, int $stationId, string $file)
	{

		/** Parametros */
		$this->clientId = $clientId;
		$this->stationId = $stationId;
		$this->file = $file;

		/** Consulta SQL */
		$this->sql = 'insert into log(client_id, 
		                              station_id,
									  file 
							) values (:client_id,
							          :station_id,
									  :file)';

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

		try {

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

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

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

			/** Retorna o ID do novo registro */
			$this->setId($this->connection->connect()->lastInsertId());

			/** Confirma a transação */
			$this->connection->connect()->commit();
			return true;
		} catch (\Exception $exception) {

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

			/** Captura o erro */
			array_push($this->errors, $exception->getMessage());
			return false;
		}
	}

	/** 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;
	}

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

		/** Consulta SQL */
		$this->sql = 'delete from log
					  where  client_id = :client_id
					  and station_id = :station_id
					  and DATE(date_post) < DATE_SUB(NOW(), INTERVAL 12 HOUR);';

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

		try {

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

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

			/** 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();

			/** Captura o erro */
			array_push($this->errors, 'Error:: ' . $exception->getMessage());
			return false;
		}
	}

	// Função para enviar uma mensagem formatada
	public function sendMessage(string $message, string $cns)
	{

		$this->cns = $cns;
		$this->message = $message;
		$this->url = "https://api.telegram.org/bot$this->botToken/sendMessage";
		$this->postFields = [
			'chat_id' => $this->chatId,
			'text' => $this->message,
			'parse_mode' => 'Markdown' // ou 'HTML'
		];

		/** Antes de enviar, verifica se não existe um evio do dia */
		if (!is_file('temp/' . date('Y-m-d-') . $this->cns . '.txt')) {


			/** Primeiramente Exclui os arquivos dos dias anteriores */

			// Define o caminho da pasta
			$this->dir = "temp";

			// Obtém o timestamp do início do dia anterior
			$this->start = strtotime("today midnight");

			// Obtém o timestamp do final do dia anterior
			$this->end = strtotime("tomorrow midnight") - 1;

			// Verifica se o diretório existe
			if (is_dir($this->dir)) {

				// Usa scandir() para obter uma lista de arquivos e pastas
				$arquivos = scandir($this->dir);

				foreach ($arquivos as $arquivo) {

					// Ignora os diretórios "." e ".."
					if ($arquivo !== "." && $arquivo !== "..") {
						$caminhoCompleto = $this->dir . DIRECTORY_SEPARATOR . $arquivo;

						// Verifica se é um arquivo e obtém o timestamp de modificação
						if (is_file($caminhoCompleto)) {
							$modificacao = filemtime($caminhoCompleto);

							// Verifica se a modificação não está no intervalo do dia atual
							if ($modificacao < $this->start || $modificacao > $this->end) {

								//Exclui o arquivo
								unlink($caminhoCompleto);
							}
						}
					}
				}
			}

			/** Após excluir os arquivos dos dias anteriores, efetua o envio do dia */
			$ch = curl_init();
			curl_setopt($ch, CURLOPT_URL, $this->url);
			curl_setopt($ch, CURLOPT_POST, true);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
			curl_setopt($ch, CURLOPT_POSTFIELDS, $this->postFields);

			/** Enviando para o bot do telegram */
			$this->response = curl_exec($ch);

			/** Carrea as informações da requisição */
			$this->info = curl_getinfo($ch);

			/** Caso a requisição tenha sido positiva, gravo o log */
			if ($this->info['http_code'] == 200) {

				// Define o nome do arquivo e o conteúdo
				$nomeArquivo = date('Y-m-d-') . $this->cns . '.txt';
				$conteudo = date('d/m/Y') . " - Envio do log para o Bot Telegram";

				// Cria ou abre o arquivo para escrita
				$arquivo = fopen('temp/' . $nomeArquivo, "w"); // 'w' cria ou sobrescreve o arquivo

				if ($arquivo) {
					// Escreve o conteúdo no arquivo
					fwrite($arquivo, $conteudo);

					// Fecha o arquivo
					fclose($arquivo);
				}
			}

			curl_close($ch);
		}
	}

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