<?php

namespace OtomaticAi\Jobs;

use Exception;
use OtomaticAi\Api\OtomaticAi\Client;
use OtomaticAi\Models\Netlinking;
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\ProcessNetlinkingFinalizeModule;
use OtomaticAi\Modules\ProcessToolboxModule;
use OtomaticAi\Modules\ProcessWordpressModule;
use OtomaticAi\Utils\Analytics;
use OtomaticAi\Utils\Auth;
use OtomaticAi\Utils\Settings;
use OtomaticAi\Vendors\Illuminate\Support\Arr;
use Throwable;

class GenerateNetlinkingJob extends Job
{
    private Netlinking $netlinking;

    /**
     * Create a new job instance.
     */
    public function __construct(Netlinking $netlinking)
    {
        $this->netlinking = $netlinking;
    }

    /**
     * Execute the job.
     */
    public function handle()
    {
        try {
            // verify that the generation can be publish
            if (!$this->canPublish()) {
                return;
            }

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

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

            // track the start of the job
            Analytics::trackEvent("generate-netlinking-start", [
                "uuid" => $this->netlinking->uuid,
                "model" => Arr::get($this->netlinking->modules, "models.text", 'gpt-4o-mini'),
                "image_model" => Arr::get($this->netlinking->modules, "models.image", 'dall-e-3'),
            ]);

            // make the generation modules
            $modules = [
                ProcessTextModule::class,
                ProcessFaqModule::class,
                ProcessImageModule::class,
                ProcessToolboxModule::class,
                ProcessAmazonModule::class,
                ProcessYoutubeModule::class,
                ProcessCustomFieldsModule::class,
                ProcessWordpressModule::class,
                ProcessNetlinkingFinalizeModule::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->netlinking)) {
                        return [
                            "name" => $class::SLUG_NAME,
                            "status" => "idle",
                        ];
                    }
                }))), "name"),
                "artifacts" => [],
            ];

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

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

    private function canPublish()
    {
        // generation not started
        if ($this->netlinking->status !== "idle")
            return false;

        // premium or trial
        if (!Auth::isPremium()) {
            return false;
        }

        // validate openai signature
        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->netlinking->addLog("Netlinking failed. " . $error->getMessage(), "_default", "error", $error->getTrace());

        // track the failure of the job
        Analytics::trackEvent("generate-netlinking-failed", [
            "uuid" => $this->netlinking->uuid,
            "model" => Arr::get($this->netlinking->modules, "models.text", 'gpt-4o-mini'),
            "image_model" => Arr::get($this->netlinking->modules, "models.image", 'dall-e-3'),
            "message" => $error->getMessage(),
        ]);

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

        // update campaign status
        $api = new Client;
        $api->updateNetlinkingCampaign($this->netlinking->uuid, [
            "status" => "failed"
        ]);
    }
}
