<?php

namespace App\Jobs\Tasks;

use App\Helpers\FirstParty\OpenAI\OpenAI;
use App\Jobs\FillPostMetadataJob;
use App\Models\Post;
use App\Models\SerpUrl;
use App\Models\SerpUrlResearch;
use App\Models\ServiceCostUsage;
use Exception;
use Mis3085\Tiktoken\Facades\Tiktoken;

class WriteWithAITask
{
    public static function handle(int $serp_url_id)
    {
        $serp_url = SerpUrl::find($serp_url_id);

        if (is_null($serp_url)) {
            return;
        }

        $serp_url_researches = SerpUrlResearch::where('serp_url_id', $serp_url->id)->where('content', '!=', 'EMPTY CONTENT')->whereNotNull('content')->get();

        $user_prompt = '';
        $total_tokens = 0;

        foreach ($serp_url_researches as $serp_url_research) {

            $sentences = self::markdownToSentences($serp_url_research->content);

            //dump($sentences);

            foreach ($sentences as $key => $sentence) {

                if ($key == 0) {
                    $user_prompt .= "ARTICLE:\n";
                }

                $current_tokens = Tiktoken::count($sentence);

                if ($current_tokens + $total_tokens > 4096) {
                    break 2;
                } else {
                    $user_prompt .= $sentence."\n";
                    $total_tokens += $current_tokens;
                }

            }
            $user_prompt .= "\n\n";
        }

        //dd($user_prompt);

        $ai_writeup_response = OpenAI::writeArticle($user_prompt, 1536, 30);

        //dd($ai_writeup_response);

        if ((isset($ai_writeup_response->output)) && (! is_empty($ai_writeup_response->output))) {
            $output = self::extractRemoveFirstHeading($ai_writeup_response->output);

            $service_cost_usage = new ServiceCostUsage;
            $service_cost_usage->cost = $ai_writeup_response->cost;
            $service_cost_usage->name = 'openai-writeArticle';
            $service_cost_usage->reference_1 = 'serp_url';
            $service_cost_usage->reference_2 = strval($serp_url->id);
            $service_cost_usage->output = $ai_writeup_response;
            $service_cost_usage->save();

            $post = Post::where('serp_url_id', $serp_url->id)->first();

            if (is_null($post)) {
                $post = new Post;
                $post->serp_url_id = $serp_url->id;
            }

            if (! is_empty($output->title)) {
                $post->title = $output->title;
            } else {

                if (! is_null($serp_url->suggestion_data)) {
                    if (isset($serp_url->suggestion_data->article_headings)) {
                        if (count($serp_url->suggestion_data->article_headings) > 0) {
                            $post->title = $serp_url->suggestion_data?->article_headings[0];
                        }
                    }
                }
            }

            if (is_empty($post->title)) {
                $post->title = $serp_url->title;
            }

            $post->slug = str_slug($post->title);

            $post->body = $output->content;

            $post->bites = null;
            $post->metadata = null;

            if ($post->save()) {
                FillPostMetadataJob::dispatch($post->id)->onQueue('default')->onConnection('default');
            }
        } else {
            throw new Exception('OpenAI failed to write');
        }
    }

    private static function markdownToSentences($markdownContent)
    {
        // Split the content on punctuation followed by a space or end of string
        $pattern = '/(?<=[.!?])\s+|\z/';

        // Split the content into sentences
        $sentences = preg_split($pattern, $markdownContent, -1, PREG_SPLIT_NO_EMPTY);

        // Return the array of sentences
        return $sentences;
    }

    private static function extractRemoveFirstHeading($markdownContent)
    {
        // Pattern to match the first markdown heading of any level
        $pattern = '/^(#+)\s*(.+)$/m';

        // Try to find the first heading
        if (preg_match($pattern, $markdownContent, $matches)) {
            $title = $matches[2]; // The first heading becomes the title

            // Remove the first heading from the content
            $updatedContent = preg_replace($pattern, '', $markdownContent, 1);

            return (object) ['title' => $title, 'content' => trim($updatedContent)];
        }

        // Return original content if no heading found
        return (object) ['title' => '', 'content' => $markdownContent];
    }
}
