<?php

namespace Breakdance\AI;

use Yethee\Tiktoken\EncoderProvider;
use function Breakdance\Data\get_global_option;
use function Breakdance\Data\set_global_option;

/**
 * @param string $content
 * @return int
 */
function countTokens($content) {
    $provider = new EncoderProvider();
    // The encoding below is specific to the newest GPT models
    // Source: https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb
    $encoder = $provider->get('cl100k_base');
    $tokens = $encoder->encode($content);
    return count($tokens);
}

/**
 * @param string $chunk
 * @return string
 */
function getChunkMessage($chunk) {
    if ($chunk != '[DONE]') {
        $arr = json_decode($chunk, true);
        if (isset($arr['choices'][0]['delta']['content'])) {
            return $arr['choices'][0]['delta']['content'];
        }
    }

    return '';
}

/**
 * @param array $messages
 * @return int
 */
function countTokensInMessages($messages) {
    $count = 0;

    foreach ($messages as $message) {
        $count += countTokens($message['content']);
    }

    return $count;
}

/**
 * @param array $messages
 * @param string $output
 * @return void
 */
function trackUsage($messages, $output) {
    $now = date('Y-m-d');
    $usage = getUsage();
    $last_usage = get_global_option('ai_last_usage') ?: $now;

    // Reset usage if it's a new day
    if ($last_usage !== $now) {
        $usage = 0;
    }

    $usage += countTokensInMessages($messages);
    $usage += countTokens($output);

    set_global_option('ai_usage', $usage);
    set_global_option('ai_last_usage', $now);
}

/**
 * @return int
 */
function getUsage() {
    $now = date('Y-m-d');

    // Reset usage if it's a new day
    if (get_global_option('ai_last_usage') !== $now) {
        resetUsage();
    }

    return get_global_option('ai_usage') ?: 0;
}

function resetUsage() {
    set_global_option('ai_usage', 0);
    set_global_option('ai_last_usage', date('Y-m-d'));
}

/**
 * @return int
 */
function getDefaultLimit() {
    return 1000000; // 1M tokens
}

/**
 * @return int
 */
function getLimit() {
    return get_global_option('ai_limit') ?: getDefaultLimit();
}

function setLimit($limit) {
    set_global_option('ai_limit', $limit);
}

/**
 * @return boolean
 */
function isRateLimited() {
    $usage = getUsage();
    $limit = getLimit();
    $now = date('Y-m-d');
    $last_usage = get_global_option('ai_last_usage') ?: $now;

    return $usage >= $limit && $now === $last_usage;
}
