<?php

namespace App\Services\Application\FacadeServices;

use App\Models\Application\AI\Completion;
use App\Facades\TemplateFacade;
use App\Interfaces\CompletionInterface;
use App\Services\Core\BaseService;
use App\Services\Core\Setting\DeliverySettingService;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use OpenAI\Laravel\Facades\OpenAI;

class CompletionFacadeService extends BaseService implements CompletionInterface
{
    protected $notAsPrompt = ['template_id', 'creativity', 'result', 'length', 'language'];

    public function __construct(Completion $completion)
    {
        $this->model = $completion;
    }

    public function index()
    {
        // TODO:
    }
    public function summary()
    {
        $auth = Auth::user();

        return $this->model->when(!$auth->isAdmin(), function ($query) use ($auth) {
            $query->where('user_id', $auth->id);
        })->select(
            DB::raw('SUM(total_tokens) as total_token'),
            DB::raw('SUM(prompt_tokens) as prompt_token'),
            DB::raw('SUM(completion_tokens) as completion_token')
        )->first();
    }

    public function store(array $request)
    {
        try {
            return Completion::create($request);
        } catch (\Exception $e) {
            return throw new \Exception($e->getMessage());
        }
    }

    public function generate(array $request)
    {
        try {

            $openai = resolve(DeliverySettingService::class)->getFormattedDeliverySettings('open_ai');

            if ($openai && isset($openai['open_ai_key']) && isset($openai['open_ai_config']) && $openai['open_ai_key'] && $openai['open_ai_config'] == 1) {

                $limit = $this->checkDailyLimit($openai);
                if (!$limit['limit']) return throw new \Exception(__t('usage_limit_over'));

                $prompt = $this->getPrompt($request);

                $result = OpenAI::completions()->create([
                    'model' => $openai['default_openai_model'] ?? 'text-davinci-003',
                    'prompt' => $prompt,
                    'n' => intval($request['result']),
                    'max_tokens' => intval($request['length']),
                    'temperature' => floatval($request['creativity']),
                ]);

                $storeData = [
                    'user_id' => Auth::id(),
                    'template_id' => $request['template_id'],
                    'uuid' => $result->id,
                    'prompt_tokens' => $result->usage->promptTokens,
                    'completion_tokens' => $result->usage->completionTokens,
                    'total_tokens' => $result->usage->totalTokens,
                ];

                $this->store($storeData);
                return $result;
            }
            return throw new \Exception(trans('default.no_ai_settings_message', ['location' => route('app-setting.view')]));
        } catch (\Exception $e) {
            return throw new \Exception($e->getMessage() ? $e->getMessage() : __t('something_went_wrong'));
        }
    }

    public function getPrompt(array $request)
    {
        $templates = TemplateFacade::cachedTemplate();

        $prompt = 'Topic: ' . $templates[$request['template_id']]['name'] . '. ';

        foreach ($request as $key => $value) {
            if (!in_array($key, $this->notAsPrompt)) {
                $key = str_replace(' ', '', ucwords(str_replace('_', ' ', $key)));
                $prompt .= $key . ': ' . $value . '. ';
            }
        }

        $prompt .= $templates[$request['template_id']]['postfix'];

        if(isset($request['language']) && $request['language']) $prompt .= ' Please write in the ' . $request['language']. ' language';

        return $prompt;
    }

    public function checkDailyLimit($openai = null): array
    {
        if(Auth::user()->isAdmin()) return ['limit' => true];

        if (!$openai) $openai = resolve(DeliverySettingService::class)->getFormattedDeliverySettings('open_ai');

        if ($openai && isset($openai['open_ai_tokens_per_use']) && isset($openai['open_ai_usage_limit'])) {
            $limit = Completion::where('user_id', Auth::id())->whereDate('created_at', Carbon::today())->select(
                DB::raw('COUNT(id) as total_completion'),
                DB::raw('SUM(total_tokens) as total_token'),
            )->first();

            if (($limit->total_token && $limit->total_token >= $openai['open_ai_tokens_per_use'])) return ['limit' => false];
            if (($limit->total_completion && $limit->total_completion >= $openai['open_ai_usage_limit'])) return ['limit' => false];

            return ['limit' => true];
        };

        return ['limit' => false];
    }
}
