<?php

namespace PortalPeople\virtualstock\components;

use yii\base\Component;
use Yii;

/**
 * Structured request/response logger for VirtualStock API calls.
 *
 * Writes log entries to the Yii2 logger at the configured level, tagged with
 * the `virtualstock` category so they can be routed independently.
 *
 * Usage (inject into VirtualStockClient or call from services):
 *   $logger->logRequest('GET', 'orders', ['limit' => 10]);
 *   $logger->logResponse('GET', 'orders', 200, ['orders' => [...]]);
 *   $logger->logError('GET', 'orders', $exception);
 */
class ApiLogger extends Component
{
    /** Yii2 log category for all VirtualStock entries. */
    public string $category = 'virtualstock';

    /** Whether to log request payloads / response bodies (disable in production if data is sensitive). */
    public bool $logBodies = false;

    /** Whether debug logging is enabled (maps to Yii2 debug level). */
    public bool $debug = false;

    /**
     * Log an outgoing API request.
     *
     * @param array<string, mixed> $params
     */
    public function logRequest(string $method, string $uri, array $params = []): void
    {
        $message = sprintf('[%s] %s', strtoupper($method), $uri);

        if ($this->logBodies && $params !== []) {
            $message .= ' ' . json_encode($params, JSON_UNESCAPED_SLASHES);
        }

        if ($this->debug) {
            Yii::debug($message, $this->category);
        } else {
            Yii::info($message, $this->category);
        }
    }

    /**
     * Log an API response.
     *
     * @param array<string, mixed> $data
     */
    public function logResponse(string $method, string $uri, int $statusCode, array $data = []): void
    {
        $message = sprintf('[%s] %s → %d', strtoupper($method), $uri, $statusCode);

        if ($this->logBodies && $data !== []) {
            $message .= ' ' . json_encode($data, JSON_UNESCAPED_SLASHES);
        }

        if ($this->debug) {
            Yii::debug($message, $this->category);
        } else {
            Yii::info($message, $this->category);
        }
    }

    /**
     * Log an API error or exception.
     */
    public function logError(string $method, string $uri, \Throwable $e): void
    {
        $message = sprintf(
            '[%s] %s → ERROR %s: %s',
            strtoupper($method),
            $uri,
            get_class($e),
            $e->getMessage()
        );

        Yii::error($message, $this->category);
    }

    /**
     * Log a rate-limit event (used when a 429 is received or the limiter fires).
     */
    public function logRateLimit(string $uri, ?string $retryAfter = null): void
    {
        $message = sprintf('[RATE_LIMIT] %s', $uri);

        if ($retryAfter !== null) {
            $message .= ' retry-after=' . $retryAfter;
        }

        Yii::warning($message, $this->category);
    }
}
