<?php

namespace CleantalkSP\SpbctWP;

use CleantalkSP\Common\Helpers\DevLogger;
use CleantalkSP\Common\LoggerRecord;

/**
 * Developer logger for SPBC WordPress plugin.
 * Replaces direct error_log() calls so the plugin keeps working when
 * error_log is disabled via disable_functions or otherwise unavailable.
 *
 * Records are persisted in the plugin's State under the `dev_log` option
 * as a ring buffer of size static::$log_limit: when exceeded, the oldest
 * entries are evicted and the newest are always saved.
 */
class SpbcDevLogger extends DevLogger
{
    /**
     * @var int Maximum number of log entries kept in the ring buffer
     */
    protected static $log_limit = 300;

    /**
     * Write a single line to the dev log.
     *
     * @param mixed $msg Main message (JSON encoded if not a string)
     * @param mixed $context Optional extra payload appended as JSON
     * @return void
     */
    public static function write($msg, $context = null)
    {
        $spbc = self::getState();
        if (!$spbc) {
            return;
        }

        $msg = is_string($msg) ? $msg : @json_encode($msg);
        if ($msg === false) {
            $msg = 'JSON_ENCODE_ERROR';
        }

        if ($context !== null) {
            $ctx = @json_encode($context);
            if ($ctx === false) {
                $ctx = 'JSON_ENCODE_ERROR';
            }
            if (!empty($ctx)) {
                $msg .= ', additional data: ' . $ctx;
            }
        }

        $record = new LoggerRecord();
        $record->time = date('Y-m-d H:i:s');
        $record->message = $msg;

        self::updateStorage($record);
    }

    /**
     * Persist a log record to the State storage with ring-buffer trimming.
     *
     * @param LoggerRecord $record
     * @return void
     */
    public static function updateStorage($record)
    {
        $spbc = self::getState();

        if (!$spbc || !($record instanceof LoggerRecord)) {
            return;
        }

        $log = self::loadStorage();
        $log[] = $record;

        if (count($log) > static::$log_limit) {
            $log = array_slice($log, -static::$log_limit);
        }

        $spbc->dev_log = $log;
        $spbc->save('dev_log', true, false);
    }

    /**
     * @return LoggerRecord[]
     */
    public static function loadStorage()
    {
        $spbc = self::getState();

        if (!$spbc) {
            return array();
        }

        $stored = $spbc->dev_log;
        if ($stored instanceof \ArrayObject) {
            $stored = $stored->getArrayCopy();
        }

        return is_array($stored) ? $stored : array();
    }

    /**
     * @return void
     * @psalm-suppress PossiblyUnusedMethod
     */
    public static function clearStorage()
    {
        $spbc = self::getState();
        if (!$spbc) {
            return;
        }

        $spbc->dev_log = array();
        $spbc->save('dev_log', true, false);
    }

    /**
     * Retrieve all logs as "time : message" formatted strings.
     *
     * @return array
     * @psalm-suppress PossiblyUnusedMethod
     */
    public static function getLogAsStringsArray()
    {
        $out = array();
        foreach (self::loadStorage() as $record) {
            if ($record instanceof LoggerRecord) {
                $out[] = $record->time . ' : ' . $record->message;
            }
        }
        return $out;
    }

    /**
     * @return State|null
     */
    public static function getState()
    {
        global $spbc;
        if (
            !isset($spbc) ||
            !is_object($spbc) ||
            !method_exists($spbc, 'save')
        ) {
            return null;
        }
        return $spbc;
    }
}
