<?php

namespace App\Http\Controllers\Api;

use App\Domains\Engine\Enums\EngineEnum;
use App\Domains\Engine\Services\FalAIService;
use App\Domains\Entity\Enums\EntityEnum;
use App\Domains\Entity\Facades\Entity;
use App\Enums\BedrockEngine;
use App\Helpers\Classes\ApiHelper;
use App\Helpers\Classes\Helper;
use App\Http\Controllers\Controller;
use App\Models\Company;
use App\Models\OpenAIGenerator;
use App\Models\Product;
use App\Models\Setting;
use App\Models\SettingTwo;
use App\Models\User;
use App\Models\UserOpenai;
use App\Services\Bedrock\BedrockRuntimeService;
use App\Services\Youtube\YoutubeTranscriptService;
use Exception;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Http\File;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use JsonException;
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
use OpenAI;
use OpenAI\Laravel\Facades\OpenAI as FacadesOpenAI;
use Random\RandomException;
use RuntimeException;
use Throwable;

class AIController extends Controller
{
    protected $client;

    protected $settings;

    protected $settings_two;

    public const STORAGE_S3 = 's3';

    public const CLOUDFLARE_R2 = 'r2';

    public const LOADING_GIF = '/themes/default/assets/img/loading.svg';

    public function __construct(BedrockRuntimeService $bedrockService)
    {
        $this->bedrockService = $bedrockService;
        $this->middleware(function (Request $request, $next) {
            ApiHelper::setOpenAiKey();

            return $next($request);
        });

        // Settings
        $this->settings = Setting::getCache();
        $this->settings_two = SettingTwo::getCache();
        set_time_limit(120);
    }

    /**
     * @OA\Post(
     *      path="/api/aiwriter/generate",
     *      operationId="buildOutputApi",
     *      tags={"AI Writer"},
     *      security={{ "passport": {} }},
     *      summary="Build AI-generated content please see the function there is custom inputs foreach template",
     *      description="Build AI-generated content based on user input.",
     *
     *      @OA\RequestBody(
     *          required=true,
     *
     *          @OA\MediaType(
     *              mediaType="multipart/form-data",
     *
     *              @OA\Schema(
     *                  type="object",
     *
     *                  @OA\Property(
     *                      property="post_type",
     *                      type="string",
     *                      enum={"post_title_generator", "article_generator", "summarize_text", "product_description", "product_name", "testimonial_review", "problem_agitate_solution", "blog_section", "blog_post_ideas", "blog_intros", "blog_conclusion", "facebook_ads", "youtube_video_description", "youtube_video_title", "youtube_video_tag", "instagram_captions", "instagram_hashtag", "social_media_post_tweet", "social_media_post_business", "facebook_headlines", "google_ads_headlines", "google_ads_description", "content_rewrite", "paragraph_generator", "pros_cons", "meta_description", "faq_generator", "email_generator", "email_answer_generator", "newsletter_generator", "grammar_correction", "tldr_summarization", "ai_image_generator", "ai_code_generator"},
     *                      example="summarize_text"
     *                  ),
     *                  @OA\Property(
     *                      property="maximum_length",
     *                      description="Maximum length of the generated text",
     *                      type="integer",
     *                      example=200
     *                  ),
     *                  @OA\Property(
     *                      property="number_of_results",
     *                      description="Number of summary results to generate",
     *                      type="integer",
     *                      example=1
     *                  ),
     *                  @OA\Property(
     *                      property="creativity",
     *                      description="Creativity level for the generated content (0 to 1)",
     *                      type="number",
     *                      example=0.75
     *                  ),
     *                  @OA\Property(
     *                      property="tone_of_voice",
     *                      description="Tone of voice for the generated content",
     *                      type="string",
     *                      example="Professional"
     *                  ),
     *                  @OA\Property(
     *                      property="language",
     *                      description="Language code for the input text",
     *                      type="string",
     *                      example="en-US"
     *                  ),
     *                  @OA\Property(
     *                      property="text_to_summary",
     *                      description="Text to be summarized",
     *                      type="string",
     *                      example="dfg"
     *                  )
     *              ),
     *          ),
     *      ),
     *
     *      @OA\Response(
     *          response=200,
     *          description="Successful operation",
     *
     *          @OA\JsonContent(
     *              type="object",
     *
     *              @OA\Property(property="message_id", type="integer", description="ID of the generated content message"),
     *              @OA\Property(property="workbook", type="object", description="Details about the generated content workbook"),
     *              @OA\Property(property="creativity", type="number", description="Creativity factor (between 0 and 1)"),
     *              @OA\Property(property="maximum_length", type="integer", description="Maximum length of the generated content"),
     *              @OA\Property(property="number_of_results", type="integer", description="Number of desired results"),
     *              @OA\Property(property="inputPrompt", type="string", description="User input prompt"),
     *              @OA\Property(property="generated_content", type="string", description="Generated content"),
     *          ),
     *      ),
     *
     *      @OA\Response(
     *          response=400,
     *          description="Bad request",
     *
     *          @OA\JsonContent(
     *              type="object",
     *
     *              @OA\Property(property="errors", type="string", description="Error message"),
     *          ),
     *      ),
     *
     *      @OA\Response(
     *          response=401,
     *          description="Unauthenticated",
     *      ),
     *      @OA\Response(
     *          response=500,
     *          description="Server error",
     *
     *          @OA\JsonContent(
     *              type="object",
     *
     *              @OA\Property(property="error", type="string", description="Internal Server Error"),
     *          ),
     *      ),
     * )
     */
    public function buildOutput(Request $request)
    {
        $user = $request->user();
        $image_generator = $request->image_generator;
        $post_type = $request->post_type;
        // SETTINGS
        $number_of_results = $request->number_of_results;
        $maximum_length = $request->maximum_length;
        $creativity = $request->creativity;
        $number_of_results = $request->number_of_results ?? 1;
        $maximum_length = $request->maximum_length ?? $this->settings->openai_max_input_length;
        $creativity = $request->creativity ?? $this->settings->openai_default_creativity;

        $language = $request->language;

        try {
            $language = explode('-', $language);
            if (count($language) > 1 && LaravelLocalization::getSupportedLocales()[$language[0]]['name']) {
                $ek = $language[1];
                $language = LaravelLocalization::getSupportedLocales()[$language[0]]['name'];
                $language .= " $ek";
            } else {
                $language = $request->language;
            }
        } catch (Throwable $th) {
            $language = $request->language;
            Log::error($language);
        }

        $negative_prompt = $request->negative_prompt;
        $tone_of_voice = $request->tone_of_voice;
        if ($request->tone_of_voice_custom) {
            $tone_of_voice = $request->tone_of_voice_custom;
        }
        if (! $tone_of_voice) {
            $tone_of_voice = $this->settings->openai_default_tone_of_voice;
        }

        // POST GENERATOR
        if ($post_type === 'post_generator') {
            $description = $request->description;
            $prompt = "Write a post about $description. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different posts. Tone of voice must be $tone_of_voice";
        }

        // POST TITLE GENERATOR
        if ($post_type === 'post_title_generator') {
            $your_description = $request->your_description;
            $prompt = "Post title about $your_description in language $language .Generate $number_of_results post titles. Tone $tone_of_voice.";
        }

        // ARTICLE GENERATOR
        if ($post_type === 'article_generator') {
            $article_title = $request->article_title;
            $focus_keywords = $request->focus_keywords;
            $prompt = "Generate article about $article_title. Focus on $focus_keywords. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different articles. Tone of voice must be $tone_of_voice";
        }

        // SUMMARY GENERATOR SUMMARIZER SUMMARIZE TEXT
        if ($post_type === 'summarize_text') {
            $text_to_summary = $request->text_to_summary;
            $tone_of_voice = $request->tone_of_voice;

            $prompt = "Summarize the following text: $text_to_summary in $language using a tone of voice that is $tone_of_voice. The summary should be no longer than $maximum_length words and set the creativity to $creativity in terms of creativity. Generate $number_of_results different summaries.";
        }

        // PRODUCT DESCRIPTION
        if ($post_type === 'product_description') {
            $product_name = $request->product_name;
            $description = $request->description;

            $prompt = "Write product description for $product_name. The language is $language. Maximum length is $maximum_length. Creativity is $creativity between 0 to 1. see the following information as a starting point: $description. Generate $number_of_results different product descriptions. Tone $tone_of_voice.";
        }

        // PRODUCT NAME
        if ($post_type === 'product_name') {
            $seed_words = $request->seed_words;
            $product_description = $request->product_description;

            $prompt = "Generate product names that will appeal to customers who are interested in $seed_words. These products should be related to $product_description. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different product names. Tone of voice must be $tone_of_voice";
        }

        // TESTIMONIAL REVIEW GENERATOR
        if ($post_type === 'testimonial_review') {
            $subject = $request->subject;
            $prompt = "Generate testimonial for $subject. Include details about how it helped you and what you like best about it. Be honest and specific, and feel free to get creative with your wording Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different testimonials. Tone of voice must be $tone_of_voice";
        }

        // PROBLEM AGITATE SOLUTION
        if ($post_type === 'problem_agitate_solution') {
            $description = $request->description;

            $prompt = "Write Problem-Agitate-Solution copy for the $description. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. problem-agitate-solution. Tone of voice must be $tone_of_voice Generate $number_of_results different Problem-Afitate-Solution.";
        }

        // BLOG SECTION
        if ($post_type === 'blog_section') {
            $description = $request->description;

            $prompt = " Write me blog section about $description. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different blog sections. Tone of voice must be $tone_of_voice";
        }

        // BLOG POST IDEAS
        if ($post_type === 'blog_post_ideas') {
            $description = $request->description;

            $prompt = "Write blog post article ideas about $description. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different blog post ideas. Tone of voice must be $tone_of_voice";
        }

        // BLOG INTROS
        if ($post_type === 'blog_intros') {
            $title = $request->title;
            $description = $request->description;

            $prompt = "Write blog post intro about title: $title. And the description is $description. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different blog intros. Tone of voice must be $tone_of_voice";
        }

        // BLOG CONCLUSION
        if ($post_type === 'blog_conclusion') {
            $title = $request->title;
            $description = $request->description;

            $prompt = "Write blog post conclusion about title: $title. And the description is $description.Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different blog conclusions. Tone of voice must be $tone_of_voice";
        }

        // FACEBOOK ADS
        if ($post_type === 'facebook_ads') {
            $title = $request->title;
            $description = $request->description;

            $prompt = "Write facebook ads text about title: $title. And the description is $description. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different facebook ads text. Tone of voice must be $tone_of_voice";
        }

        // YOUTUBE VIDEO DESCRIPTION
        if ($post_type === 'youtube_video_description') {
            $title = $request->title;

            $prompt = "write youtube video description about $title. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different youtube video descriptions. Tone of voice must be $tone_of_voice";
        }

        // YOUTUBE VIDEO TITLE
        if ($post_type === 'youtube_video_title') {
            $description = $request->description;

            $prompt = "Craft captivating, attention-grabbing video titles about $description for YouTube rankings. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different youtube video titles. Tone of voice must be $tone_of_voice";
        }

        // YOUTUBE VIDEO TAG
        if ($post_type === 'youtube_video_tag') {
            $title = $request->title;

            $prompt = "Generate tags and keywords about $title for youtube video. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different youtube video tags. Tone of voice must be $tone_of_voice";
        }

        // INSTAGRAM CAPTIONS
        if ($post_type === 'instagram_captions') {
            $title = $request->title;

            $prompt = "Write instagram post caption about $title. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different instagram captions. Tone of voice must be $tone_of_voice";
        }

        // INSTAGRAM HASHTAG
        if ($post_type === 'instagram_hashtag') {
            $keywords = $request->keywords;

            $prompt = "Write instagram hastags for $keywords. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different instagram hashtags. Tone of voice must be $tone_of_voice";
        }

        // SOCIAL MEDIA POST TWEET
        if ($post_type === 'social_media_post_tweet') {
            $title = $request->title;

            $prompt = "Write in 1st person tweet about $title. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different tweets. Tone of voice must be $tone_of_voice";
        }

        // SOCIAL MEDIA POST BUSINESS
        if ($post_type === 'social_media_post_business') {
            $company_name = $request->company_name;
            $provide = $request->provide;
            $description = $request->description;

            $prompt = "Write in company social media post, company name: $company_name. About: $description. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different social media posts. Tone of voice must be $tone_of_voice";
        }

        // FACEBOOK HEADLINES
        if ($post_type === 'facebook_headlines') {
            $title = $request->title;
            $description = $request->description;

            $prompt = "Write Facebook ads title about title: $title. And description is $description. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different facebook ads title. Tone of voice must be $tone_of_voice";
        }

        // GOOGLE ADS HEADLINES
        if ($post_type === 'google_ads_headlines') {
            $product_name = $request->product_name;
            $description = $request->description;
            $audience = $request->audience;

            $prompt = "Write Google ads headline product name: $product_name. Description is $description. Audience is $audience. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different google ads headlines. Tone of voice must be $tone_of_voice";
        }

        // GOOGLE ADS DESCRIPTION
        if ($post_type === 'google_ads_description') {
            $product_name = $request->product_name;
            $description = $request->description;
            $audience = $request->audience;

            $prompt = "Write google ads description product name: $product_name. Description is $description. Audience is $audience. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different google ads description. Tone of voice must be $tone_of_voice";
        }

        // CONTENT REWRITE
        if ($post_type === 'content_rewrite') {
            $contents = $request->contents;

            $prompt = "Rewrite content:  '$contents'. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different rewrited content. Tone of voice must be $tone_of_voice";
        }

        // PARAGRAPH GENERATOR
        if ($post_type === 'paragraph_generator') {
            $description = $request->description;
            $keywords = $request->keywords;

            $prompt = "Generate one paragraph about:  '$description'. Keywords are $keywords. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different paragraphs. Tone of voice must be $tone_of_voice";
        }

        // Pros & Cons
        if ($post_type === 'pros_cons') {
            $title = $request->title;
            $description = $request->description;

            $prompt = "Generate pros & cons about title:  '$title'. Description is $description. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different pros&cons. Tone of voice must be $tone_of_voice";
        }

        // META DESCRIPTION
        if ($post_type === 'meta_description') {
            $title = $request->title;
            $description = $request->description;
            $keywords = $request->keywords;

            $prompt = "Generate website meta description site name: $title. Description is $description. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different meta descriptions. Tone of voice must be $tone_of_voice";
        }

        // FAQ Generator (All datas)
        if ($post_type === 'faq_generator') {
            $title = $request->title;
            $description = $request->description;

            $prompt = "Answer like faq about subject: $title Description is $description. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different faqs. Tone of voice must be $tone_of_voice";
        }

        // Email Generator
        if ($post_type === 'email_generator') {
            $subject = $request->subject;
            $description = $request->description;

            $prompt = "Write email about title: $subject, description: $description. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different emails. Tone of voice must be $tone_of_voice";
        }

        // Email Answer Generator
        if ($post_type === 'email_answer_generator') {
            $description = $request->description;

            $prompt = "answer this email content: $description. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different email answers. Tone of voice must be $tone_of_voice";
        }

        // Newsletter Generator
        if ($post_type === 'newsletter_generator') {
            $description = $request->description;
            $subject = $request->subject;
            $title = $request->title;

            $prompt = "generate newsletter template about product_title: $title, reason: $subject description: $description. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different newsletter template. Tone of voice must be $tone_of_voice";
        }

        // Grammar Correction
        if ($post_type === 'grammar_correction') {
            $description = $request->description;

            $prompt = "Correct this to standard $language. Text is '$description'. Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different grammar correction. Tone of voice must be $tone_of_voice";
        }

        // TL;DR summarization
        if ($post_type === 'tldr_summarization') {
            $description = $request->description;

            $prompt = "$description. Tl;dr Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Language is $language. Generate $number_of_results different tl;dr. Tone of voice must be $tone_of_voice";
        }

        // AI Rewriter
        if ($post_type === 'ai_rewriter') {
            $content_rewrite = $request->content_rewrite;
            $rewrite_mode = $request->rewrite_mode;

            $prompt = "Original Content: $content_rewrite.\n\n\nMust Rewrite content with $rewrite_mode mode differently with original content. Result language is $language \n";
        }

        if ($post_type === 'ai_image_generator') {
            $imageParam = $request->all();
        }

        if ($post_type === 'ai_video') {
            $videoParam = $request->all();
        }

        if ($post_type === 'ai_code_generator') {
            $description = $request->description;
            $code_language = $request->code_language;
            $prompt = "Write a code about $description, in $code_language";
        }

        $post = OpenAIGenerator::where('slug', $post_type)->first();

        if ($post->custom_template == 1) {
            // $custom_template = OpenAIGenerator::find($request->openai_id);
            $custom_template = $post;
            $prompt = $custom_template->prompt;
            foreach (json_decode($custom_template->questions) as $question) {
                $question_name = '**' . $question->name . '**';
                $prompt = str_replace($question_name, $request[$question->name], $prompt);
            }

            $prompt .= " in $language language. Number of results should be $number_of_results. And the maximum length of $maximum_length characters";
            if ($creativity !== 'undefined') {
                $prompt .= " Creativity is $creativity between 0 and 1.";
            }
            if ($tone_of_voice !== 'undefined') {
                $prompt .= " Tone of voice must be $tone_of_voice.";
            }
        }

        if ($post->type == 'youtube') {
            $language = $request->language;
            $youtube_action = $request->youtube_action;
            if ($youtube_action == 'blog') {
                $prompt = "You are blog writer. Turn the given transcript text into a blog post in and translate to {$language} language. Group the content and create a subheading (with HTML-h2) for each group (without HTML body or head tags or backticks ```html). Maximum $maximum_length words. Creativity is $creativity between 0 and 1. Generate $number_of_results different articles. Tone of voice must be $tone_of_voice. Content:";
            } elseif ($youtube_action == 'short') {
                $prompt = "You are transcript editor. Make sense of the given content and explain the main idea. Your result must be in {$language} language. Creativity is $creativity between 0 and 1. Generate $number_of_results different articles. Tone of voice must be $tone_of_voice. Content:";
            } elseif ($youtube_action == 'list') {
                $prompt = "You are transcript editor. Make sense of the given content and make a list main ideas. Your result must be in {$language} language. Creativity is $creativity between 0 and 1. Generate $number_of_results different articles. Tone of voice must be $tone_of_voice. Content:";
            } elseif ($youtube_action == 'tldr') {
                $prompt = "You are transcript editor. Make short TLDR. Your result must be in {$language} language. Creativity is $creativity between 0 and 1. Generate $number_of_results different articles. Tone of voice must be $tone_of_voice. Content:";
            } elseif ($youtube_action == 'prons_cons') {
                $prompt = "You are transcript editor. Make short pros and cons. Your result must be in {$language} language. Creativity is $creativity between 0 and 1. Generate $number_of_results different articles. Tone of voice must be $tone_of_voice. Content:";
            }

            $videoUrl = $request->url;

            $data = (new youtubeTranscriptService)
                ->getTranscript($videoUrl);
            $transcripts = json_decode($data->content(), true);

            if (isset($transcripts['captions'])) {
                $prompt .= $transcripts['captions'] . "\n";
            } else {
                return response()->json([
                    'status'  => 'error',
                    'message' => __('There are no captions available in the video.'),
                ], 401);
            }
        }

        if ($post->type == 'rss') {
            $language = $request->language;
            $prompt = "write blog post about {$request->title}. Group the content and create a subheading (with HTML-h2) for each group (without HTML body or head tags or backticks ```html).";
            $prompt .= "Your result must be in $language language. Number of results should be $number_of_results. And the maximum length of $maximum_length characters. Tone of voice must be $tone_of_voice. Creativity is $creativity between 0 and 1.";
        }

        // check if there is a company input included in the request
        if ($request->company) {
            $company = Company::find($request->company);
            $product = Product::find($request->product);
            if ($company) {
                if (! isset($prompt)) {
                    $prompt = '';
                }
                $type = $product->type == 0 ? 'Service' : 'Product';
                $prompt .= ".\n Focus on my company and {$type}'s information: \n";
                // Company information
                if ($company->name) {
                    $prompt .= "The company's name is {$company->name}. ";
                }
                // explode industry
                $industry = explode(',', $company->industry);
                $count = count($industry);
                if ($count > 0) {
                    $prompt .= 'The company is in the ';
                    foreach ($industry as $index => $ind) {
                        $prompt .= $ind;
                        if ($index < $count - 1) {
                            $prompt .= ' and ';
                        }
                    }
                }

                if ($company->website) {
                    $prompt .= ". The company's website is {$company->website}. ";
                }

                if ($company->target_audience) {
                    $prompt .= "The company's target audience is: {$company->target_audience}. ";
                }

                if ($company->tagline) {
                    $prompt .= "The company's tagline is {$company->tagline}. ";
                }

                if ($company->description) {
                    $prompt .= "The company's description is {$company->description}. ";
                }
                if ($product) {
                    // Product information
                    if ($product->key_features) {
                        $prompt .= "The {$product->type}'s key features are {$product->key_features}. ";
                    }

                    if ($product->name) {
                        $prompt .= "The {$product->type}'s name is {$product->name}. \n";
                    }
                }
            }
        }

        if ($post->type === 'text' || $post->type === 'rss' || $post->type === 'youtube') {
            return $this->textOutput($prompt, $post, $creativity, $maximum_length, $number_of_results, $user);
        }

        if ($post->type === 'code') {
            return $this->codeOutput($prompt, $post, $user);
        }

        if ($post->type === 'image') {
            return $this->imageOutput($imageParam, $post, $user);
        }

        if ($post->type === 'video') {
            return $this->videoOutput($videoParam, $post, $user);
        }

        if ($post->type === 'audio') {
            $file = $request->file('file');

            return $this->audioOutput($file, $post, $user);
        }

        if ($post->type === 'isolator') {
            $request->validate([
                'file' => 'required|file|mimes:ogg,mpga,mp3,mp4,mpeg,m4a,wav,webm',
            ], [
                'file.mimes' => __('Invalid file extension, accepted extensions are ogg, mp3, mp4, mpeg, mpga, m4a, wav, and webm.'),
                'file.max'   => __('The file size must not exceed 500 MB.'),
            ]);
            $file = $request->file('file');

            return $this->audioIsolator($file, $post, $user);
        }
    }

    public function textOutput($prompt, $post, $creativity, $maximum_length, $number_of_results, $user): JsonResponse
    {
        $entry = UserOpenai::create([
            'team_id'   => $user->team_id,
            'title'     => request('title') ?: __('New Workbook'),
            'slug'      => str()->random(7) . str($user->fullName())->slug() . '-workbook',
            'user_id'   => $user->id,
            'openai_id' => $post->id,
            'input'     => $prompt,
            'response'  => null,
            'output'    => null,
            'hash'      => str()->random(256),
            'credits'   => 0,
            'words'     => 0,
        ]);

        $message_id = $entry->id;
        $workbook = $entry;
        $inputPrompt = $prompt;

        return response()->json(compact('message_id', 'creativity', 'maximum_length', 'number_of_results', 'inputPrompt', 'workbook'));
    }

    /**
     * @throws JsonException
     */
    public function codeOutput($prompt, $post, $user): JsonResponse
    {
        $driver = Entity::driver();
        $driver->redirectIfNoCreditBalance();
        if ($driver->enum()->value === EntityEnum::TEXT_DAVINCI_003->value) {
            $response = FacadesOpenAI::completions()->create([
                'model'      => $driver->enum()->value,
                'prompt'     => $prompt,
                'max_tokens' => (int) $this->settings->openai_max_output_length,
            ]);
        } else {
            $response = FacadesOpenAI::chat()->create([
                'model'    => $driver->enum()->value,
                'messages' => [
                    ['role' => 'user', 'content' => $prompt],
                ],
            ]);
        }
        $entry = new UserOpenai([
            'team_id'     => $user->team_id,
            'title'       => request('title') ?: __('New Workbook'),
            'slug'        => Str::random(7) . Str::slug($user->fullName()) . '-workbook',
            'user_id'     => Auth::id(),
            'openai_id'   => $post->id,
            'input'       => $prompt,
            'response'    => json_encode($response->toArray(), JSON_THROW_ON_ERROR),
        ]);

        if ($driver->enum()->value === EntityEnum::TEXT_DAVINCI_003->value) {
            $entry->output = $response['choices'][0]['text'];
        } else {
            $entry->output = $response->choices[0]->message->content;
        }
        $entry->hash = Str::random(256);
        $entry->credits = countWords($entry->output);
        $entry->words = 0;
        $entry->save();

        $driver->input($entry->output)->calculateCredit()->decreaseCredit();

        return response()->json(compact('post', 'entry'));
    }

    public function imageOutput($param, $post, $user): JsonResponse
    {
        $lockKey = 'generate_image_output_lock';
        if (! Cache::lock($lockKey, 10)->get()) { // Attempt to acquire lock
            return response()->json(['message' => 'Image generation in progress. Please try again later.'], 409);
        }

        $engineCheck = match ($param['image_generator']) {
            'flux-pro' => EngineEnum::FAL_AI->value,
            default    => $param['image_generator'],
        };
        $entries = [];

        try {
            $engine = EngineEnum::fromSlug($engineCheck);
            $model = $this->getDefaultModel($engine);
            $code = $this->getEngineCode($engine);
            $number_of_images = (int) $param['image_number_of_images'];

            $driver = Entity::driver($model)->inputImageCount($number_of_images)->calculateCredit();
            $chkLmt = Helper::checkImageDailyLimit();
            if ($chkLmt->getStatusCode() === 429) {
                return $chkLmt;
            }
            $driver->redirectIfNoCreditBalance();
            $apiKey = $this->getOpenAiApiKey($user);
            config(['openai.api_key' => $apiKey]);
            set_time_limit(120);

            for ($i = 0; $i < $number_of_images; $i++) {
                $imageDetails = $this->processImageGeneration($engine, $model, $param);
                $savePath = $this->saveImageOutputToStorage($imageDetails);
                $entry = $this->saveEntryToDatabase($imageDetails, $user, $post, $code, $savePath);
                $entry->img_id = 'img-' . $entry->response . '-' . $entry->id;
                $entries[] = $entry;
            }
            $driver->decreaseCredit();
            Cache::lock($lockKey)->release();

        } catch (Exception $e) {
            return response()->json(['status' => 'error', 'message' => $e->getMessage()]);
        } finally {
            Cache::lock($lockKey)->forceRelease();
        }

        return response()->json(['status' => 'success', 'images' => $entries, 'image_storage' => $this->settings_two->ai_image_storage]);
    }

    public function audioOutput($file, $post, $user)
    {
        $driver = Entity::driver(EntityEnum::WHISPER_1);
        $driver->redirectIfNoCreditBalance();
        $path = 'uploads/audio/';
        $file_name = Str::random(4) . '-' . Str::slug($user->fullName()) . '-audio.' . $file->getClientOriginalExtension();

        // Audio Extension Control
        $imageTypes = ['mp3', 'mp4', 'mpeg', 'mpga', 'm4a', 'wav', 'webm'];
        if (! in_array(Str::lower($file->getClientOriginalExtension()), $imageTypes)) {
            $data = [
                'errors' => ['Invalid extension, accepted extensions are mp3, mp4, mpeg, mpga, m4a, wav, and webm.'],
            ];

            return response()->json($data, 419);
        }

        $file->move($path, $file_name);
        $fullPath = $path . $file_name;

        $response = FacadesOpenAI::audio()->transcribe([
            'file'            => fopen($fullPath, 'rb'),
            'model'           => EntityEnum::WHISPER_1->value,
            'response_format' => 'verbose_json',
        ]);

        $text = $response->text;

        UserOpenai::create([
            'team_id'   => $user->team_id,
            'title'     => request('title') ?: __('New Workbook'),
            'slug'      => Str::random(7) . Str::slug($user->fullName()) . '-speech-to-text-workbook',
            'user_id'   => $user->id,
            'openai_id' => $post->id,
            'input'     => $fullPath,
            'response'  => json_encode($response->toArray(), JSON_THROW_ON_ERROR),
            'output'    => $text,
            'hash'      => Str::random(256),
            'credits'   => countWords($text),
            'words'     => countWords($text),
        ]);

        $driver->input($text)->calculateCredit()->decreaseCredit();
        $userOpenai = UserOpenai::where('user_id', Auth::id())->where('openai_id', $post->id)->orderBy('created_at', 'desc')->get();
        $openai = OpenAIGenerator::find($post->id);

        return response()->json(compact('userOpenai', 'openai'));
    }

    public function finalizeOutput($post, $entry): JsonResponse // not used. see line 546
    {
        // Workbook add-on
        $workbook = $entry;
        $html = view('panel.user.openai.documents_workbook_textarea', compact('workbook'))->render();
        $userOpenai = UserOpenai::where('user_id', Auth::id())->where('openai_id', $post->id)->orderBy('created_at', 'desc')->get();
        $openai = OpenAIGenerator::find($post->id);
        $html2 = view('panel.user.openai.components.generator_sidebar_table', compact('userOpenai', 'openai'))->render();

        return response()->json(compact('html', 'html2'));
    }

    private function getOpenAiApiKey(?User $user): string
    {
        return ApiHelper::setOpenAiKey();
    }

    private function getStableApiKey(): string
    {
        $stableDiffusionKeys = explode(',', $this->settings_two->stable_diffusion_api_key);

        return $stableDiffusionKeys[array_rand($stableDiffusionKeys)];
    }

    /**
     * Get the default model based on the AI engine.
     *
     * @throws Exception
     */
    private function getDefaultModel(?EngineEnum $engine): ?EntityEnum
    {
        return match ($engine) {
            EngineEnum::OPEN_AI          => $this->getDefaultOpenAiImageModel(),
            EngineEnum::STABLE_DIFFUSION => $this->getStableDiffusionDefaultModel(),
            EngineEnum::FAL_AI           => $this->getDefaultFalAiModel(),

            default                      => throw new Exception(__('Invalid AI Engine')),
        };
    }

    /**
     * Process image generation based on the AI engine.
     *
     * @throws Exception|GuzzleException
     */
    private function processImageGeneration(?EngineEnum $engine, ?EntityEnum $model, array $param): array
    {
        return match ($engine) {
            EngineEnum::OPEN_AI          => $this->processOpenAIImage($model, $param),
            EngineEnum::STABLE_DIFFUSION => $this->processStableDiffusionImage($model, $param),
            EngineEnum::FAL_AI           => $this->processFalAIImage($model, $param),

            default                      => throw new Exception(__('Invalid AI Engine')),
        };
    }

    private function processOpenAIImage(?EntityEnum $model, array $param): array
    {
        $is_demo = Helper::appIsDemo();
        $size = $param['size'];
        $description = $param['description'];
        $style = $param['image_style'] ?? null;
        $lighting = $param['image_lighting'] ?? null;
        $mood = $param['mood'] ?? null;
        $quality = $param['quality'];
        $prompt = $description;
        if (is_null($prompt)) {
            throw new RuntimeException(__('You must provide a prompt'));
        }
        $attributes = [
            'style'    => $style ? "$style style" : null,
            'lighting' => $lighting ? "$lighting lighting" : null,
            'mood'     => $mood ? "$mood mood" : null,
        ];
        $prompt .= ' ' . implode(' ', array_filter($attributes));
        $response = FacadesOpenAI::images()->create([
            'model'           => $model,
            'prompt'          => $prompt,
            'size'            => $is_demo ? $this->getDemoImageSize($model) : $size,
            'response_format' => 'b64_json',
            'quality'         => $is_demo ? 'standard' : $quality,
            'n'               => 1,
        ]);
        $contents = base64_decode($response['data'][0]['b64_json']);
        $nameOfImage = Str::random(12) . '-DALL-E-' . Str::slug(explode(' ', mb_substr($prompt, 0, 15))[0]) . '.png';

        return [
            'prompt'                => $prompt,
            'imageContent'          => $contents,
            'nameOfImage'           => $nameOfImage,
        ];
    }

    /**
     * @throws GuzzleException
     * @throws RandomException
     * @throws JsonException
     */
    private function processStableDiffusionImage(?EntityEnum $model, array $param): array
    {
        $stable_type = $param['type'];
        $prompt = $param['stable_description'];
        if (is_null($prompt)) {
            throw new RuntimeException(__('You must provide a prompt'));
        }

        $negative_prompt = $param['negative_prompt'];
        $style_preset = $param['style_preset'];
        $sampler = $param['sampler'];
        $clip_guidance_preset = $param['clip_guidance_preset'];
        $image_resolution = $param['image_resolution'];
        $init_image = $param['image_src'] ?? null;
        $mood = $param['mood'] ?? null;
        $defaultSdModel = $this->getStableDiffusionDefaultModel()->value;

        $v2BetaModels = [
            EntityEnum::SD_3->value,
            EntityEnum::SD_3_TURBO->value,
            EntityEnum::SD_3_MEDIUM->value,
            EntityEnum::SD_3_LARGE->value,
            EntityEnum::SD_3_LARGE_TURBO->value,
            EntityEnum::CORE->value,
            EntityEnum::ULTRA->value,
        ];
        $width = (int) explode('x', $image_resolution)[0];
        $height = (int) explode('x', $image_resolution)[1];

        if ($defaultSdModel === BedrockEngine::BEDROCK->value && $stable_type === 'text-to-image') {
            $response = $this->bedrockService->invokeStableDiffusion($prompt, random_int(1, 1000000), $width, $height);
            $nameOfImage = Str::random(12) . '-AWS-SD-' . Str::slug(explode(' ', mb_substr($prompt, 0, 15))[0]) . '.png';

            return [
                'prompt'                => $prompt,
                'imageContent'          => $response,
                'nameOfImage'           => $nameOfImage,
            ];
        }
        $stableDiffusionKey = $this->getStableApiKey();
        if (empty($stableDiffusionKey)) {
            throw new RuntimeException(__('You must provide a StableDiffusion API Key.'));
        }

        $sd3Payload = [];
        $baseUri = in_array($defaultSdModel, $v2BetaModels, true) && in_array($stable_type, ['text-to-image', 'image-to-image'], true)
            ? 'https://api.stability.ai/v2beta/stable-image/generate/'
            : 'https://api.stability.ai/v1/generation/';
        $contentType = ($stable_type === 'upscale' || $stable_type === 'image-to-image') ? 'multipart/form-data' : 'application/json';
        $client = new Client([
            'base_uri' => $baseUri,
            'headers'  => [
                'Content-Type'  => $contentType,
                'Authorization' => 'Bearer ' . $stableDiffusionKey,
                'Accept'        => 'application/json',
            ],
        ]);
        $payload = [
            'cfg_scale'            => 7,
            'clip_guidance_preset' => $clip_guidance_preset ?? 'NONE',
            'samples'              => 1,
            'steps'                => 50,
        ];
        if ($sampler) {
            $payload['sampler'] = $sampler;
        }
        if ($style_preset) {
            $payload['style_preset'] = $style_preset;
        }
        $content_type = 'json';
        switch ($stable_type) {
            case 'multi-prompt':
                $stable_url = 'text-to-image';
                $payload['width'] = $width;
                $payload['height'] = $height;
                $arr = [];
                foreach ($prompt as $p) {
                    $arr[] = [
                        'text'   => $p . ($mood === null ? '' : (' ' . $mood . ' mood.')),
                        'weight' => 1,
                    ];
                }
                $prompt = $arr;
                $payload['text_prompts'] = $prompt;

                break;
            case 'upscale':
                $content_type = 'multipart';
                $stable_url = 'image-to-image/upscale';
                $defaultSdModel = 'esrgan-v1-x2plus';
                $payload = [];
                $payload['image'] = $init_image->get();
                $prompt = [
                    [
                        'text'   => $prompt . '-' . Str::random(16),
                        'weight' => 1,
                    ],
                ];

                break;
            case 'image-to-image':
                $content_type = 'multipart';
                $stable_url = $stable_type;
                $payload['init_image'] = $init_image->get();
                $sd3Payload = [
                    [
                        'name'     => 'prompt',
                        'contents' => $prompt,
                    ],
                    [
                        'name'     => 'mode',
                        'contents' => 'image-to-image',
                    ],
                    [
                        'name'     => 'strength',
                        'contents' => 0,
                    ],
                    [
                        'name'     => 'image',
                        'contents' => $init_image->get(),
                        'filename' => $init_image->getClientOriginalName(),
                    ],
                ];
                $prompt = [
                    [
                        'text'   => $prompt . ($mood === null ? '' : (' ' . $mood . ' mood.')),
                        'weight' => 1,
                    ],
                ];
                $payload['text_prompts'] = $prompt;

                break;
            default:
                $stable_url = $stable_type;
                $payload['width'] = $width;
                $payload['height'] = $height;
                $sd3Payload = [
                    [
                        'name'     => 'prompt',
                        'contents' => $prompt,
                    ],
                    [
                        'name'     => 'file',
                        'contents' => 'no',
                    ],
                    [
                        'name'     => 'output_format',
                        'contents' => 'png',
                    ],
                ];
                $prompt = [
                    [
                        'text'   => $prompt . ($mood === null ? '' : (' ' . $mood . ' mood.')),
                        'weight' => 1,
                    ],
                ];
                $payload['text_prompts'] = $prompt;

                break;
        }
        if ($negative_prompt) {
            $prompt[] = ['text' => $negative_prompt, 'weight' => -1];
        }
        if ($content_type === 'multipart') {
            $multipart = [];
            foreach ($payload as $key => $value) {
                if (! is_array($value)) {
                    $multipart[] = ['name' => $key, 'contents' => $value];

                    continue;
                }
                foreach ($value as $multiKey => $multiValue) {
                    $multiName = $key . '[' . $multiKey . ']' . (is_array($multiValue) ? '[' . key($multiValue) . ']' : '') . '';
                    $multipart[] = ['name' => $multiName, 'contents' => (is_array($multiValue) ? reset($multiValue) : $multiValue)];
                }
            }
            $payload = $multipart;
        }

        try {
            if (in_array($defaultSdModel, $v2BetaModels, true) && in_array($stable_type, ['text-to-image', 'image-to-image'], true)) {
                $defaultSdModel = 'sd3';
                $sd3Payload[] = ['name' => 'model', 'contents' => $defaultSdModel];
                $response = $client->post($defaultSdModel, [
                    'headers'   => ['accept' => 'application/json'],
                    'multipart' => $sd3Payload,
                ]);
            } else {
                $defaultSdModel = $stable_type === 'multi-prompt' ? EntityEnum::STABLE_DIFFUSION_V_1_6->value : $defaultSdModel;
                $response = $client->post("$defaultSdModel/$stable_url", [
                    $content_type => $payload,
                ]);
            }
        } catch (Exception $e) {
            if ($e->hasResponse()) {
                $errorMessage = $e->getResponse()->getBody()->getContents();
                $errorData = json_decode($errorMessage, true, 512, JSON_THROW_ON_ERROR);
                if (isset($errorData['message'])) {
                    throw new RuntimeException($errorData['message']);
                }

                throw new RuntimeException($e->getMessage());
            }

            throw new RuntimeException($e->getMessage());
        }

        $body = $response->getBody();
        if ($response->getStatusCode() === 200) {
            $nameOfPrompt = explode(' ', mb_substr($prompt[0]['text'], 0, 15))[0];
            $nameOfImage = Str::random(12) . '-STABLE-' . $nameOfPrompt . '.png';
            if (
                ($stable_type === 'text-to-image' || $stable_type === 'image-to-image') && in_array($defaultSdModel, $v2BetaModels, true)
            ) {
                $contents = base64_decode(json_decode($body, false, 512, JSON_THROW_ON_ERROR)->image);
            } else {
                $contents = base64_decode(json_decode($body, false, 512, JSON_THROW_ON_ERROR)->artifacts[0]->base64);
            }
        } else {
            if ($body->status === 'error') {
                $message = $body->message;
            } else {
                $message = __('Failed, Try Again');
            }

            throw new RuntimeException($message);
        }

        return [
            'prompt'                => $prompt[0]['text'],
            'imageContent'          => $contents,
            'nameOfImage'           => $nameOfImage,
        ];
    }

    private function processFalAIImage(?EntityEnum $model, array $param): array
    {
        $prompt = $param['description_flux_pro'];
        $requestId = FalAIService::generate($prompt, $model);

        return [
            'engine'                => EngineEnum::FAL_AI,
            'requestId'             => $requestId,
            'status'                => 'IN_QUEUE',
            'output'                => asset(self::LOADING_GIF),
            'prompt'                => $prompt,
            'imageContent'          => null,
            'nameOfImage'           => Str::random(12) . '-FLUX-' . Str::slug(explode(' ', mb_substr($prompt, 0, 15))[0]) . '.png',
        ];
    }

    private function saveEntryToDatabase(array $imageDetails, User $user, OpenAIGenerator $post, string $code, string $savePath): UserOpenai
    {
        $data = [
            'team_id'   => $user->team_id,
            'title'     => $imageDetails['nameOfImage'],
            'slug'      => Str::random(7) . Str::slug($user->fullName()) . '-workbook',
            'user_id'   => $user->id,
            'openai_id' => $post->id,
            'input'     => $imageDetails['prompt'],
            'response'  => $code,
            'output'    => ThumbImage(url($savePath)),
            'hash'      => Str::random(256),
            'credits'   => 1,
            'words'     => 0,
            'storage'   => $this->settings_two->ai_image_storage,
            'payload'   => request()?->all(),
        ];
        if (isset($imageDetails['engine']) && $imageDetails['engine'] === EngineEnum::FAL_AI) {
            $data['request_id'] = $imageDetails['requestId'];
            $data['status'] = $imageDetails['status'];
            $data['output'] = $imageDetails['output'];
        }

        return UserOpenai::create($data);
    }

    private function saveImageOutputToStorage(array $imageDetails): string
    {
        if (isset($imageDetails['engine']) && $imageDetails['engine'] === EngineEnum::FAL_AI) {
            return '/';
        }

        $image_storage = $this->settings_two->ai_image_storage;

        return match ($image_storage) {
            self::STORAGE_S3    => $this->saveImageToS3($imageDetails),
            self::CLOUDFLARE_R2 => $this->saveImageToR2($imageDetails),
            default             => $this->saveImageToLocal($imageDetails),
        };
    }

    private function saveImageToS3(array $imageDetails): string
    {
        $localPath = $this->saveImageToLocal($imageDetails);

        try {
            $uploadedFile = new File($localPath);
            $aws_path = Storage::disk('s3')->put('', $uploadedFile);
            unlink($localPath);
            $fullAWSPath = Storage::disk('s3')->url($aws_path);
        } catch (Exception $e) {
            throw new RuntimeException('AWS Error - ' . $e->getMessage());
        }

        return $fullAWSPath;
    }

    private function saveImageToLocal(array $imageDetails): string
    {
        Storage::disk('public')->put($imageDetails['nameOfImage'], $imageDetails['imageContent']);

        return 'uploads/' . $imageDetails['nameOfImage'];
    }

    private function saveImageToR2(array $imageDetails): string
    {
        Storage::disk('r2')->put($imageDetails['nameOfImage'], $imageDetails['imageContent']);

        return Storage::disk('r2')->url($imageDetails['nameOfImage']);
    }

    private function getEngineCode(?EngineEnum $engine): string
    {
        return match ($engine) {
            EngineEnum::STABLE_DIFFUSION => 'SD',
            EngineEnum::FAL_AI           => 'FL',
            default                      => 'DE',
        };
    }

    private function getDemoImageSize(?EntityEnum $model): string
    {
        return match ($model) {
            EntityEnum::DALL_E_3 => '1024x1024',
            EntityEnum::DALL_E_2 => '256x256',
            default              => '512x512',
        };
    }

    private function getDefaultOpenAiImageModel(): EntityEnum
    {
        $default = match ($this->settings_two->dalle) {
            'dalle3' => EntityEnum::DALL_E_3->slug(),
            'dalle2' => EntityEnum::DALL_E_2->slug(),
            default  => $this->settings_two->dalle,
        };

        return EntityEnum::fromSlug($default) ?? EntityEnum::DALL_E_2;
    }

    private function getStableDiffusionDefaultModel(): EntityEnum
    {
        return EntityEnum::fromSlug($this->settings_two?->stablediffusion_default_model) ?? EntityEnum::SD_3;
    }

    private function getDefaultFalAiModel(): EntityEnum
    {
        return EntityEnum::fromSlug(setting('fal_ai_default_model', EntityEnum::FLUX_PRO->value)) ?? EntityEnum::FLUX_PRO;
    }

    /**
     * @throws \GuzzleHttp\Exception\GuzzleException
     * @throws Throwable
     * @throws JsonException
     */
    public function audioIsolator($file, $post, $user)
    {
        $driver = Entity::driver(EntityEnum::ISOLATOR);
        $driver->redirectIfNoCreditBalance();
        set_time_limit(3000);
        $apiKey = $this->settings_two->elevenlabs_api_key;
        $mp3File = $file->getRealPath();
        $mp3FileName = $file->getClientOriginalName();
        $client = new Client;
        $response = $client->request('POST', 'https://api.elevenlabs.io/v1/audio-isolation', [
            'headers' => [
                'xi-api-key' => $apiKey,
            ],
            'multipart' => [
                [
                    'name'     => 'audio',
                    'contents' => fopen($mp3File, 'r'),
                    'filename' => $mp3FileName,
                ],
            ],
            'timeout' => 3000,
        ]);
        $resAudio = $response->getBody();
        $characterCost = $response->getHeader('character-cost');
        if (count($characterCost) > 0) {
            $characterCost = $characterCost[0];
        } else {
            $characterCost = 0;
        }
        $defaultWordChars = 5;
        $wordsCount = $characterCost / $defaultWordChars;

        $driver->input($characterCost)->calculateCredit()->decreaseCredit();

        $audioName = $user->id . '-' . Str::random(20) . '.mp3';
        Storage::disk('public')->put($audioName, $resAudio);
        $ai = OpenAIGenerator::whereSlug('ai_voice_isolator')->first();

        $langsAndVoices['language'][] = 'en-US';
        $langsAndVoices['voices'][] = $audioName;

        $entry = UserOpenai::create([
            'team_id'   => $user->team_id,
            'output'    => $audioName,
            'input'     => $audioName,
            'title'     => __('Isolated Voice'),
            'slug'      => Str::random(20) . Str::slug($user->fullName()) . '-isolated-voice',
            'user_id'   => $user->id,
            'hash'      => Str::random(256),
            'openai_id' => $ai->id,
        ]);

        $entry->response = json_encode($langsAndVoices, JSON_THROW_ON_ERROR);

        $entry->credits = $wordsCount;
        $entry->words = $wordsCount;
        $entry->save();

        $userOpenai = UserOpenai::where('user_id', Auth::id())->where('openai_id', $ai->id)->orderBy('created_at', 'desc')->paginate(10);
        $userOpenai->withPath(route('dashboard.user.openai.generator', 'ai_voice_isolator'));
        $openai = OpenAIGenerator::where('id', $ai->id)->first();

        return response()->json(compact('userOpenai', 'openai'));
    }
}
