<?php

namespace OtomaticAi\Modules;

use Exception;
use OtomaticAi\Api\OtomaticAi\Client;
use OtomaticAi\Content\CustomHtml;
use OtomaticAi\Content\Amazon\Amazon;
use OtomaticAi\Models\Contracts\Publishable;
use OtomaticAi\Models\Presets\Preset;
use OtomaticAi\Modules\Contracts\Module as ModuleContract;
use OtomaticAi\Utils\Settings;
use OtomaticAi\Utils\Support;
use OtomaticAi\Vendors\Illuminate\Support\Arr;

class ProcessAmazonModule extends Module implements ModuleContract
{
    const SLUG_NAME = "process_amazon_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("Amazon module started.", self::SLUG_NAME);

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

        try {
            $amazons = [];
            foreach ($placeholders as $placeholder) {
                $amazons[] = $this->generateAmazon($placeholder);
            }

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

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

                    return "";
                }
            });

            // 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("Amazon module completed successfully.", self::SLUG_NAME, "success");
        } catch (Exception $e) {
            $this->publication->addLog("Amazon module failed. " . $e->getMessage(), self::SLUG_NAME, "warning");
        }
    }

    private function generateAmazon(array $placeholder): ?Amazon
    {
        $search = Arr::get($placeholder, "search");
        $template = Arr::get($placeholder, "template");
        $length = Arr::get($placeholder, "length");

        if (empty($search)) {
            return null;
        }

        if (empty($template) || !in_array($template, ["list", "grid_1x", "grid_2x", "grid_3x"])) {
            $template = $this->getModuleValue("content.automatic.amazon.template", "grid_3x");
        }

        if (empty($length)) {
            $length = $this->getModuleValue("content.automatic.amazon.max_products", 3);
        }

        $store = Settings::get("amazon.store", "fr");
        $length = intval($length);

        try {
            $api = new Client;
            $result = $api->amazonSearch($search, $store);

            $products = is_array($result) ? $result : [];

            if (!empty($products)) {
                $products = array_slice($products, 0, $length);

                return new Amazon($template, $products);
            }
        } catch (Exception $e) {
            $this->publication->addLog("Amazon module failed. " . $e->getMessage(), self::SLUG_NAME, "warning");
        }

        return null;
    }

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

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

    static public function isEnabled(Publishable $publishable): bool
    {
        $isAmazonType = self::getPublicationType($publishable) === "amazon_comparator" || self::getPublicationType($publishable) === "amazon_product";

        return $isAmazonType || self::getPublicationModuleValue($publishable, "content.automatic.amazon.enabled", false);
    }
}
