<?php
namespace Incoviba\Common\Implement\Log;

use PDOStatement;
use Monolog\Handler\AbstractProcessingHandler;
use Monolog\LogRecord;
use Monolog\Level;
use Incoviba\Common\Define\Connection;

class MySQLHandler extends AbstractProcessingHandler
{
    private bool $initialized = false;
    private PDOStatement $statement;

    public function __construct(protected Connection $connection, protected int $retainDays = 90, int|string|Level $level = Level::Debug, bool $bubble = true)
    {
        parent::__construct($level, $bubble);
    }
    public function write(LogRecord $record): void
    {
        if (!$this->initialized) {
            $this->initialized();
        }
        $this->cleanup();
        $this->statement->execute([
            'channel' => $record->channel,
            'level' => $record->level->getName(),
            'message' => $record->formatted,
            'time' => $record->datetime->format('Y-m-d H:i:s.u'),
            'context' => (count($record->context) > 0) ? json_encode($record->context, JSON_UNESCAPED_SLASHES) : '',
            'extra' => (count($record->extra) > 0) ? json_encode($record->extra, JSON_UNESCAPED_SLASHES) : ''
        ]);
    }

    private function initialized(): void
    {
        $query = <<<QUERY
CREATE TABLE IF NOT EXISTS monolog (
    channel VARCHAR(255),
    level VARCHAR(100),
    message LONGTEXT,
    time DATETIME,
    context LONGTEXT,
    extra LONGTEXT
)
QUERY;
        $this->connection->getPDO()->exec($query);
        $query = <<<QUERY
INSERT INTO monolog (channel, level, message, time, context, extra)
VALUES (:channel, :level, :message, :time, :context, :extra)
QUERY;
        $this->statement = $this->connection->getPDO()->prepare($query);
        $this->initialized = true;
    }
    private function cleanup(): void
    {
        $query = "DELETE FROM monolog WHERE time < DATE_SUB(CURDATE(), INTERVAL {$this->retainDays} DAY)";
        $this->connection->query($query);
    }
}
