<?php

namespace OtomaticAi\Modules;

use Exception;
use OtomaticAi\Api\OtomaticAi\Client;
use OtomaticAi\Content\Video\Youtube;
use OtomaticAi\Models\Contracts\Publishable;
use OtomaticAi\Modules\Contracts\Module as ModuleContract;
use OtomaticAi\Vendors\Illuminate\Support\Arr;
use OtomaticAi\Vendors\Illuminate\Support\Str;

class ProcessYoutubeModule extends Module implements ModuleContract
{
    const SLUG_NAME = "process_youtube_module";

    /**
     * Execute the job.
     *
     * @return void
     * @throws Exception
     */
    public function handle(): void
    {
        // verify that the job is runnable
        if (!$this->isRunnable()) {
            return;
        }

        // log the start of the job
        $this->publication->addLog("Youtube module started.", self::SLUG_NAME);

        // get length
        $length = $this->getLength();

        // create youtube placeholders
        $placeholders = $this->createElementPlaceholders("youtube");

        try {
            // make the search terms
            $search = $this->makeSearch($this->getTitle());

            // call the api
            $api = new Client;
            $result = $api->youtube($search, $this->getLanguage()->key);

            // get the videos
            $videos = is_array($result) ? $result : [];

            // randomize videos
            $videos = Arr::shuffle($videos);

            if (!empty($videos)) {

                // get x random posts
                $videos = Arr::random($videos, min(count($videos), $length));
                $videos = array_map(function ($video) {
                    return new Youtube($video["id"], $video["title"]);
                }, $videos);

                // replace youtube placeholders with the generated videos
                $this->replaceElementPlaceholders("youtube", function ($attributes) use ($videos) {
                    $index = Arr::get($attributes, "index");
                    if ($index !== null && isset($videos[$index])) {
                        $video = $videos[$index];

                        $el = $video->toHtmlElement($this->html);
                        if ($el) {
                            return $el;
                        }
                    }
                });

                // add the html content to the generation state
                $this->generationState->setArtifact("html_content", trim(preg_replace("/^<body>|<\/body>$/", "", $this->html->saveHTML($this->html->getElementsByTagName("body")->item(0)))));

                // log the end of the job
                $this->publication->addLog("Youtube module completed successfully.", self::SLUG_NAME, "success");
            } else {
                $this->publication->addLog("Youtube module failed. No videos found.", self::SLUG_NAME, "warning");
            }
        } catch (Exception $e) {
            $this->publication->addLog("Youtube module failed. " . $e->getMessage(), self::SLUG_NAME, "warning");
        }
    }

    /**
     * Make the Youtube search terms for the provided search
     *
     * @param string $search
     * @return string
     * @throws Exception
     */
    private function makeSearch(string $search): string
    {
        $search = Str::lower($search);

        return $search;
    }

    /**
     * Get the number of Youtube elements
     *
     * @return integer
     */
    private function getLength(): int
    {
        return $this->countElements("youtube");;
    }

    /**
     * Determine if the module is runnable
     *
     * @return boolean
     */
    public function isRunnable(): bool
    {
        // must have youtube elements
        return $this->getLength() > 0;
    }

    static public function isEnabled(Publishable $publishable): bool
    {
        if (!self::getPublicationModuleValue($publishable, "content.automatic.youtube.enabled", false)) {
            return false;
        }

        return true;
    }
}
