<?php

namespace OtomaticAi\Jobs;

use Exception;
use OtomaticAi\Models\Publication;
use OtomaticAi\Modules\ProcessAmazonModule;
use OtomaticAi\Modules\ProcessCustomFieldsModule;
use OtomaticAi\Modules\ProcessTextModule;
use OtomaticAi\Modules\ProcessImageModule;
use OtomaticAi\Modules\ProcessYoutubeModule;
use OtomaticAi\Modules\ProcessFaqModule;
use OtomaticAi\Modules\ProcessFinalizeModule;
use OtomaticAi\Modules\ProcessToolboxModule;
use OtomaticAi\Modules\ProcessWordpressModule;
use OtomaticAi\Utils\Analytics;
use OtomaticAi\Utils\Auth;
use OtomaticAi\Utils\Settings;
use OtomaticAi\Vendors\Carbon\Carbon;
use OtomaticAi\Vendors\Illuminate\Support\Arr;
use Throwable;

class PublishPublicationJob extends Job
{
    /**
     * The publication to publish.
     *
     * @var Publication
     */
    private Publication $publication;

    /**
     * Create a new job instance.
     */
    public function __construct(Publication $publication)
    {
        $this->publication = $publication;
        $this->publication->load('project', 'project.persona');
    }

    /**
     * Execute the job.
     */
    public function handle()
    {
        try {

            // verify that the publication can be publish
            if (!$this->canPublish()) {
                return;
            }

            // clear publication logs
            $this->publication->clearLogs();

            // set the publication status to pending
            $this->publication->status = "pending";
            $this->publication->save();

            // track the start of the job
            Analytics::trackEvent("publish-job-start", [
                "title" => $this->publication->title,
                "type" => $this->publication->project->type,
                "model" => Arr::get($this->publication->project->modules, "models.text", 'gpt-4o-mini'),
                "image_model" => Arr::get($this->publication->project->modules, "models.image", 'dall-e-3'),
                "is_automatic_mode" => Arr::get($this->publication->project->modules, "content.automatic.enabled", false),
            ]);

            // make the generation modules
            $modules = [
                ProcessTextModule::class,
                ProcessFaqModule::class,
                ProcessImageModule::class,
                ProcessToolboxModule::class,
                ProcessAmazonModule::class,
                ProcessYoutubeModule::class,
                ProcessCustomFieldsModule::class,
                ProcessWordpressModule::class,
                ProcessFinalizeModule::class,
            ];

            // instantiate modules jobs
            $generationState = [
                "version" => 1,
                "status" => "running",
                "current_step" => "process_text_module",
                "steps" => Arr::keyBy(Arr::values(Arr::whereNotNull(Arr::map($modules, function ($class) {
                    if ($class::isEnabled($this->publication)) {
                        return [
                            "name" => $class::SLUG_NAME,
                            "status" => "idle",
                        ];
                    }
                }))), "name"),
                "artifacts" => [],
            ];

            // set the generation state
            $this->publication->generation_state = $generationState;
            $this->publication->save();

            // dispatch the first step
            ProcessPublicationStepJob::dispatch(["id" => $this->publication->id, "model_class" => $this->publication->getMorphClass()], 5);
        } catch (Throwable $e) {
            return $this->fail($e);
        }
    }

    private function canPublish()
    {
        // project must be enabled
        if (!$this->publication->project->enabled)
            return false;

        // publication must be idle
        if ($this->publication->status !== "idle")
            return false;

        // publication published_at must be in the past
        if ($this->publication->published_at->greaterThan(Carbon::now()))
            return false;

        // publication parent page must be published
        if (Arr::get($this->publication->project->modules, 'wordpress.post_type', 'post') === 'page') {
            $parent = $this->publication->parent;
            if ($parent && $parent->status !== 'success')
                return false;
        }

        // user must be premium
        if (!Auth::isPremium()) {
            return false;
        }

        // validate openai signature must be valid
        try {
            $response = Auth::validateOpenAISignature(Settings::get("api.openai.api_key"));
            if (!Arr::get($response, "success", false)) {
                return false;
            }
        } catch (Exception $e) {
            return false;
        }

        return true;
    }

    private function fail(Throwable $error)
    {
        $this->publication->addLog("Publication failed. " . $error->getMessage(), "_default", "error", $error->getTrace());

        // track the failure of the job
        Analytics::trackEvent("publish-job-failed", [
            "title" => $this->publication->title,
            "type" => $this->publication->project->type,
            "model" => Arr::get($this->publication->project->modules, "models.text", 'gpt-4o-mini'),
            "image_model" => Arr::get($this->publication->project->modules, "models.image", 'dall-e-3'),
            "is_automatic_mode" => Arr::get($this->publication->project->modules, "content.automatic.enabled", false),
            "message" => $error->getMessage(),
        ]);

        $this->publication->status = "failed";
        $this->publication->save();
    }
}
