<?php

namespace OtomaticAi\Models;

use DOMDocument;
use DOMXPath;
use OtomaticAi\Casts\Language;
use OtomaticAi\Content\Image\Image;
use OtomaticAi\Models\Contracts\Publishable;
use OtomaticAi\Models\WP\Post;
use OtomaticAi\Traits\HasLogs;
use OtomaticAi\Utils\Gutemberg;
use OtomaticAi\Vendors\Carbon\Carbon;
use OtomaticAi\Vendors\Illuminate\Database\Eloquent\Builder;
use OtomaticAi\Vendors\Illuminate\Database\Eloquent\Model;
use OtomaticAi\Vendors\Illuminate\Support\Arr;

class SingleModeGeneration extends Model implements Publishable
{
    use HasLogs;

    protected $fillable = [
        "language",
        "type",
        "settings",
        "title",
        "status",
        "generation_state",
        "meta",
        "content"
    ];

    /**
     * Create a new Eloquent model instance.
     *
     * @param  array  $attributes
     * @return void
     */
    public function __construct(array $attributes = [])
    {
        global $wpdb;

        $this->table = $wpdb->prefix . 'otomatic_ai_single_mode_generations';

        parent::__construct($attributes);
    }

    /**
     * The accessors to append to the model's array form.
     *
     * @var array
     */
    protected $appends = ['edit_link', 'display_link', 'html_content', 'thumbnail', 'is_not_started'];

    protected $casts = [
        'language' => Language::class,
        'settings' => 'array',
        'meta' => 'array',
        'logs' => 'array',
        'extras' => 'array',
        'generated_at' => 'datetime',
        'generation_state' => 'array',
    ];

    /**
     * Get the wp post that owns the publication.
     */
    public function post()
    {
        return $this->belongsTo(Post::class, "post_id");
    }

    /**
     * Get the persona that owns the project.
     */
    public function persona()
    {
        return $this->belongsTo(Persona::class);
    }

    /**
     * Scope a query to only include published publications.
     */
    public function scopePublished(Builder $query): void
    {
        $query->where('status', 'success');
    }

    /**
     * Scope a query to only include idle publications.
     */
    public function scopeIdle(Builder $query): void
    {
        $query->where('status', 'idle');
    }

    /**
     * Scope a query to only include pending publications.
     */
    public function scopePending(Builder $query): void
    {
        $query->where('status', 'pending');
    }

    /**
     * Scope a query to only include failed publications.
     */
    public function scopeFailed(Builder $query): void
    {
        $query->where('status', 'failed');
    }

    public function getSettingsAttribute()
    {
        $settings = [
            "models" => [
                "text" => "gpt-4o-mini",
                "image" => "flux_1_dev",
            ],

            "writing_style" => null,

            "sources" => [
                "enabled" => false,
                "no_follow" => false,
                "blank" => false,
            ],

            "generation_brief" => "",

            "data" => [
                "serp" => [
                    "enabled" => true,
                ],
                "links" => [],
            ],

            "custom_instructions" => [
                "profile" => null,
                "images" => null,
            ],

            "text_length" => "medium",
            "images" => [
                "thumbnail" => [
                    "enabled" => true,
                ],
                "content" => [
                    "enabled" => true,
                    "max_images" => 3
                ],
            ],
            "youtube" => [
                "enabled" => true,
            ],
            "embeds" => [
                "enabled" => true,
            ],
            "internal_links" => [
                "enabled" => true,
                "no_follow" => false,
            ],
            "external_links" => [
                "enabled" => true,
                "no_follow" => false,
            ],
            "custom_links" => [
                "enabled" => false,
                "links" => [],
            ],
            "lists" => [
                "enabled" => true,
            ],
            "tables" => [
                "enabled" => true,
            ],
            "toolbox" => [
                "enabled" => false,
                "template" => "automatic",
            ],
            "code" => [
                "enabled" => true,
            ],
            "bold_words" => [
                "enabled" => true,
            ],
            "emojis" => [
                "enabled" => false,
            ],
            "summary" => [
                "enabled" => false,
            ],
            "faq" => [
                "enabled" => false,
            ],
            "keywords" => [
                "custom" => [],
            ],
            "amazon" => [
                "enabled" => false,
                "template" => "grid_3x",
                "max_products" => 3,
            ],

            "seo_title" => null,
            "seo_description" => null,
        ];

        $oldSettings = json_decode($this->attributes["settings"], true);
        $s = Arr::merge($oldSettings, $settings);

        // convert old text models
        $s = Project::convertOldTextModels($s);

        // convert old image models
        $s = Project::convertOldImageModels($s);

        // convert custom data links to data links
        if (!empty(Arr::get($oldSettings, "custom_data.links", [])) && empty(Arr::get($s, "data.links", []))) {
            Arr::set($s, "data.links", Arr::get($oldSettings, "custom_data.links", []));
        }

        // convert custom data data to generation brief
        if (!empty(Arr::get($oldSettings, "custom_data.data", "")) && empty(Arr::get($s, "generation_brief", ""))) {
            Arr::set($s, "generation_brief", Arr::get($oldSettings, "custom_data.data", ""));
        }

        return $s;
    }

    public function getModulesAttribute()
    {
        return self::settingsToModules($this->settings);
    }

    public function getIsNotStartedAttribute()
    {
        if ($this->status === 'idle') {
            return $this->updated_at->diffInSeconds(Carbon::now()) > 300; // 5 minutes
        }

        return false;
    }

    public static function settingsToModules(array $settings)
    {
        $modules = [
            "_version" => Project::$version,
            "models" => [
                "text" => "gpt-4o-mini",
                "image" => "flux_1_dev"
            ],
            "content" => [
                "writing_style" => null,
                "generation_brief" => "",
                "data" => [
                    "serp" => [
                        "enabled" => true,
                    ],
                    "links" => [],
                ],
                "custom_instructions" => [
                    "profile" => null,
                    "images" => null,
                ],
                "automatic" => [
                    "enabled" => true,
                    "text_length" => "medium",
                    "images" => [
                        "enabled" => true,
                        "max_images" => 3
                    ],
                    "youtube" => [
                        "enabled" => true,
                    ],
                    "embeds" => [
                        "enabled" => true,
                    ],
                    "internal_links" => [
                        "enabled" => true,
                    ],
                    "external_links" => [
                        "enabled" => true,
                    ],
                    "custom_links" => [
                        "enabled" => false,
                        "links" => [],
                    ],
                    "lists" => [
                        "enabled" => true,
                    ],
                    "tables" => [
                        "enabled" => true,
                    ],
                    "toolbox" => [
                        "enabled" => false,
                        "template" => "automatic",
                    ],
                    "code" => [
                        "enabled" => true,
                    ],
                    "bold_words" => [
                        "enabled" => true,
                    ],
                    "emojis" => [
                        "enabled" => false,
                    ],
                    "summary" => [
                        "enabled" => false,
                    ],
                    "faq" => [
                        "enabled" => false,
                    ],
                    "keywords" => [
                        "automatic" => [
                            "enabled" => false,
                        ],
                        "custom" => [],
                    ],
                    "amazon" => [
                        "enabled" => false,
                        "template" => "grid_3x",
                        "max_products" => 3,
                    ],
                ],
            ],
            "wordpress" => [
                "thumbnail" => [
                    "enabled" => true,
                ],
            ]
        ];

        // set models
        Arr::set($modules, "models.text", Arr::get($settings, "models.text", "gpt-4o-mini"));
        Arr::set($modules, "models.image", Arr::get($settings, "models.image", "flux_1_dev"));

        // set content options
        Arr::set($modules, "content.writing_style", Arr::get($settings, "writing_style"));
        Arr::set($modules, "content.generation_brief", Arr::get($settings, "generation_brief", ""));
        Arr::set($modules, "content.data.serp.enabled", Arr::get($settings, "data.serp.enabled", true));
        Arr::set($modules, "content.data.links", Arr::get($settings, "data.links", []));
        Arr::set($modules, "content.custom_instructions.profile", Arr::get($settings, "custom_instructions.profile"));
        Arr::set($modules, "content.custom_instructions.images", Arr::get($settings, "custom_instructions.images"));
        Arr::set($modules, "content.automatic.text_length", Arr::get($settings, "text_length"));
        Arr::set($modules, "content.automatic.images.enabled", Arr::get($settings, "images.content.enabled", true));
        Arr::set($modules, "content.automatic.images.max_images", Arr::get($settings, "images.content.max_images", 1));
        Arr::set($modules, "content.automatic.youtube.enabled", Arr::get($settings, "youtube.enabled", true));
        Arr::set($modules, "content.automatic.embeds.enabled", Arr::get($settings, "embeds.enabled", true));
        Arr::set($modules, "content.automatic.internal_links.enabled", Arr::get($settings, "internal_links.enabled", true));
        Arr::set($modules, "content.automatic.internal_links.no_follow", Arr::get($settings, "internal_links.no_follow", false));
        Arr::set($modules, "content.automatic.external_links.enabled", Arr::get($settings, "external_links.enabled", true));
        Arr::set($modules, "content.automatic.external_links.no_follow", Arr::get($settings, "external_links.no_follow", false));
        Arr::set($modules, "content.automatic.custom_links.enabled", Arr::get($settings, "custom_links.enabled", false));
        Arr::set($modules, "content.automatic.custom_links.links", array_values(
            array_filter(Arr::get($settings, "custom_links.links", []), function ($link) {
                return !empty($link["url"]);
            })
        ));

        Arr::set($modules, "content.automatic.lists.enabled", Arr::get($settings, "lists.enabled", true));
        Arr::set($modules, "content.automatic.tables.enabled", Arr::get($settings, "tables.enabled", true));
        Arr::set($modules, "content.automatic.toolbox.enabled", Arr::get($settings, "toolbox.enabled", false));
        Arr::set($modules, "content.automatic.toolbox.template", Arr::get($settings, "toolbox.template", "automatic"));
        Arr::set($modules, "content.automatic.bold_words.enabled", Arr::get($settings, "bold_words.enabled", true));
        Arr::set($modules, "content.automatic.emojis.enabled", Arr::get($settings, "emojis.enabled", false));
        Arr::set($modules, "content.automatic.summary.enabled", Arr::get($settings, "summary.enabled", false));
        Arr::set($modules, "content.automatic.faq.enabled", Arr::get($settings, "faq.enabled", false));
        Arr::set($modules, "content.automatic.keywords.custom", Arr::get($settings, "keywords.custom", []));
        Arr::set($modules, "content.automatic.amazon.enabled", Arr::get($settings, "amazon.enabled", false));
        Arr::set($modules, "content.automatic.amazon.template", Arr::get($settings, "amazon.template", "grid_3x"));
        Arr::set($modules, "content.automatic.amazon.max_products", Arr::get($settings, "amazon.max_products", 3));

        // set wordpress options
        Arr::set($modules, "wordpress.thumbnail.enabled", Arr::get($settings, "images.thumbnail.enabled", true));

        return $modules;
    }

    public static function modulesToSettings(array $modules)
    {
        $settings = [
            "models" => [
                "text" => Arr::get($modules, "models.text", "gpt-4o-mini"),
                "image" => Arr::get($modules, "models.image", "flux_1_dev"),
            ],
            "writing_style" => Arr::get($modules, "content.writing_style"),
            "sources" => [
                "enabled" => Arr::get($modules, "content.sources.enabled", false),
                "no_follow" => Arr::get($modules, "content.sources.no_follow", false),
                "blank" => Arr::get($modules, "content.sources.blank", false),
            ],
            "generation_brief" => Arr::get($modules, "content.generation_brief", ""),
            "data" => [
                "serp" => [
                    "enabled" => Arr::get($modules, "content.data.serp.enabled", true),
                ],
                "links" => Arr::get($modules, "content.data.links", []),
            ],
            "custom_instructions" => [
                "profile" => Arr::get($modules, "content.custom_instructions.profile"),
                "images" => Arr::get($modules, "content.custom_instructions.images"),
            ],
            "text_length" => Arr::get($modules, "content.automatic.text_length"),
            "images" => [
                "thumbnail" => [
                    "enabled" => Arr::get($modules, "wordpress.thumbnail.enabled", true),
                ],
                "content" => [
                    "enabled" => Arr::get($modules, "content.automatic.images.enabled", true),
                    "max_images" => Arr::get($modules, "content.automatic.images.max_images", 1),
                ]
            ],
            "youtube" => [
                "enabled" => Arr::get($modules, "content.automatic.youtube.enabled", true),
            ],
            "embeds" => [
                "enabled" => Arr::get($modules, "content.automatic.embeds.enabled", true),
            ],
            "external_links" => [
                "enabled" => Arr::get($modules, "content.automatic.external_links.enabled", true),
                "no_follow" => Arr::get($modules, "content.automatic.external_links.no_follow", false),
            ],
            "internal_links" => [
                "enabled" => Arr::get($modules, "content.automatic.internal_links.enabled", true),
                "no_follow" => Arr::get($modules, "content.automatic.internal_links.no_follow", false),
            ],
            "custom_links" => [
                "enabled" => Arr::get($modules, "content.automatic.custom_links.enabled", false),
                "links" => Arr::get($modules, "content.automatic.custom_links.links", []),
            ],
            "lists" => [
                "enabled" => Arr::get($modules, "content.automatic.lists.enabled", true),
            ],
            "tables" => [
                "enabled" => Arr::get($modules, "content.automatic.tables.enabled", true),
            ],
            "toolbox" => [
                "enabled" => Arr::get($modules, "content.automatic.toolbox.enabled", false),
                "template" => Arr::get($modules, "content.automatic.toolbox.template", "automatic"),
            ],
            "bold_words" => [
                "enabled" => Arr::get($modules, "content.automatic.bold_words.enabled", true),
            ],
            "emojis" => [
                "enabled" => Arr::get($modules, "content.automatic.emojis.enabled", false),
            ],
            "summary" => [
                "enabled" => Arr::get($modules, "content.automatic.summary.enabled", false),
            ],
            "faq" => [
                "enabled" => Arr::get($modules, "content.automatic.faq.enabled", false),
            ],
            "keywords" => [
                "custom" => Arr::get($modules, "content.automatic.keywords.custom", []),
            ],
        ];

        return $settings;
    }

    /**
     * Get the wordpress edit link of the post publication.
     */
    public function getEditLinkAttribute()
    {
        if ($this->post_id !== null) {
            return get_edit_post_link($this->post_id, 'json');
        }

        return null;
    }

    /**
     * Get the wordpress display link of the post publication.
     */
    public function getDisplayLinkAttribute()
    {
        if ($this->post_id !== null) {
            return get_permalink($this->post_id);
        }

        return null;
    }

    public function getGenerationTitleAttribute()
    {
        if (!empty(Arr::get($this->meta, "base_title"))) {
            return Arr::get($this->meta, "base_title") . ' : ' . $this->title;
        }

        return $this->title;
    }

    public function getThumbnailAttribute(): ?array
    {
        $attachmentId = Arr::get($this->extras, "thumbnail.attachment");

        if (!empty($attachmentId)) {
            $srcs = wp_get_attachment_image_src($attachmentId, "full");
            if (!empty($srcs)) {
                $thumbnail = Arr::get($this->extras, "thumbnail");
                $thumbnail["src"] = $srcs[0];
                return $thumbnail;
            }
        }

        return null;
    }

    public function getHtmlContentAttribute()
    {
        $elements = [
            "image" => "otoimage",
            "youtube" => "otoyoutube",
            "facebook" => "otofacebook",
            "instagram" => "otoinstagram",
            "tiktok" => "ototiktok",
            "twitter" => "ototwitter",
            "faq" => "otofaq",
        ];

        // load html
        $doc = new DOMDocument('1.0', 'UTF-8');
        libxml_use_internal_errors(true);
        $doc->loadHTML('<?xml encoding="UTF-8">' . $this->content, LIBXML_NOWARNING);
        libxml_use_internal_errors(false);

        // create xpath
        $xpath = new DOMXPath($doc);

        foreach ($elements as $elementKey => $tagName) {

            // get the nodes
            $nodes = $xpath->query("//{$tagName}");

            foreach ($nodes as $node) {

                $displayElement = null;
                switch ($elementKey) {
                    case "image":
                        $displayElement = Image::fromHtmlElement($node);
                        break;
                }

                if (!empty($displayElement)) {
                    $display = $displayElement->toDisplayElement($node);

                    if (!empty($display)) {
                        $node->parentNode->replaceChild($display, $node);
                    } else {
                        $node->parentNode->removeChild($node);
                    }
                }
            }
        }

        // return the html
        return preg_replace("/^<body>|<\/body>$/", "", $doc->saveHTML($doc->getElementsByTagName("body")->item(0)));
    }

    public function toWordpress()
    {
        $content = wp_encode_emoji($this->content);

        $converter = new Gutemberg();
        return $converter->convert_blocks($content);
    }
}
