<?php

namespace GriffinForms\Includes\Ai;

use GriffinForms\Traits\Singleton;

/**
 * ButlerTokenManager
 *
 * Tracks and aggregates token usage returned by the AI transport layer.
 * Persists a rolling usage summary into the native plugin Options table
 * under the 'gf_assist_token_stats' key.
 *
 * Data shape for 'gf_assist_token_stats':
 * [
 *   'total_prompt_tokens'     => int,
 *   'total_completion_tokens' => int,
 *   'total_tokens'            => int,
 *   'request_count'           => int,
 *   'last_updated'            => 'Y-m-d H:i:s' (UTC),
 * ]
 *
 * V1 writes on every request. The abstraction supports buffered flushing
 * in a future release by overriding flush().
 *
 * @since 3.0.1.0
 */
class ButlerTokenManager
{
    use Singleton;

    const OPTION_KEY = 'gf_assist_token_stats';

    protected $settings;

    protected function __construct()
    {
        $this->settings = \GriffinForms\Settings::getInstance();
    }

    /**
     * Record token usage from a successful AI broker response.
     * Silently no-ops if the response contains no usage data.
     *
     * @param array $response The raw response array from AiBroker::request().
     * @return void
     */
    public function record(array $response): void
    {
        if (empty($response['success']) || !isset($response['raw']['usage'])) {
            return;
        }

        $usage = $response['raw']['usage'];

        $prompt_tokens     = (int) ($usage['prompt_tokens'] ?? 0);
        $completion_tokens = (int) ($usage['completion_tokens'] ?? 0);
        $total_tokens      = (int) ($usage['total_tokens'] ?? ($prompt_tokens + $completion_tokens));

        $current = $this->getStats();

        $updated = [
            'total_prompt_tokens'     => $current['total_prompt_tokens'] + $prompt_tokens,
            'total_completion_tokens' => $current['total_completion_tokens'] + $completion_tokens,
            'total_tokens'            => $current['total_tokens'] + $total_tokens,
            'request_count'           => $current['request_count'] + 1,
            'last_updated'            => gmdate('Y-m-d H:i:s'),
        ];

        $this->flush($updated);
    }

    /**
     * Retrieve current aggregated stats from the Options table.
     *
     * @return array
     */
    public function getStats(): array
    {
        $raw = $this->settings->getOption(self::OPTION_KEY);

        if (is_array($raw) && isset($raw['total_tokens'])) {
            return $raw;
        }

        return $this->defaultStats();
    }

    /**
     * Reset all token counters to zero.
     *
     * @return void
     */
    public function reset(): void
    {
        $this->flush($this->defaultStats());
    }

    /**
     * Persist the stats array to the Options table.
     * Override in a subclass to buffer writes instead of flushing immediately.
     *
     * @param array $stats
     * @return void
     */
    protected function flush(array $stats): void
    {
        $this->settings->updateOption(self::OPTION_KEY, $stats, 'ai');
    }

    /**
     * Default zero-state stats shape.
     *
     * @return array
     */
    protected function defaultStats(): array
    {
        return [
            'total_prompt_tokens'     => 0,
            'total_completion_tokens' => 0,
            'total_tokens'            => 0,
            'request_count'           => 0,
            'last_updated'            => null,
        ];
    }
}
