<?php

/**
 * Created by Reliese Model.
 */

namespace App\Models;

use AlAminFirdows\LaravelEditorJs\Facades\LaravelEditorJs;
use Carbon\Carbon;
use GrahamCampbell\Markdown\Facades\Markdown;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Spatie\Feed\Feedable;
use Spatie\Feed\FeedItem;
use Symfony\Component\DomCrawler\Crawler;

/**
 * Class Post
 *
 * @property int $id
 * @property string|null $title
 * @property string|null $slug
 * @property string|null $excerpt
 * @property int|null $author_id
 * @property string $featured_image
 * @property string $editor
 * @property array|null $body
 * @property string $post_format
 * @property int $comment_count
 * @property int $likes_count
 * @property string $status
 * @property Carbon|null $created_at
 * @property Carbon|null $updated_at
 * @property Author|null $author
 * @property Collection|PostCategory[] $post_categories
 */
class Post extends Model implements Feedable
{
    protected $table = 'posts';

    protected $casts = [
        'author_id' => 'int',
        'body' => 'json',
        'comment_count' => 'int',
        'likes_count' => 'int',
        'featured' => 'bool',
        'publish_date' => 'datetime',
    ];

    protected $fillable = [
        'title',
        'slug',
        'cliffhanger',
        'excerpt',
        'author_id',
        'featured_image',
        'editor',
        'body',
        'post_format',
        'comment_count',
        'likes_count',
        'status',
        'featured',
        'publish_date',
    ];

    protected $appends = [
        //'html_body',
    ];

    public function author()
    {
        return $this->belongsTo(Author::class);
    }

    public function post_categories()
    {
        return $this->hasMany(PostCategory::class);
    }

    public function post_category()
    {
        return $this->hasOne(PostCategory::class);
    }

    public function getHtmlBodyAttribute()
    {
        if (! is_empty($this->body)) {
            if ($this->editor == 'editorjs') {
                return LaravelEditorJs::render(json_encode($this->body));
            } elseif ($this->editor == 'markdown') {
                //dd($this->body);

                $html = Markdown::convert($this->body)->getContent();

                //dd($html);

                $html = str_replace('\\n', "\n", $html);

                $crawler = new Crawler($html);

                $firstHeaderProcessed = false;

                $crawler->filter('h1, h2, h3, h4, h5, h6')->each(function (Crawler $node) use (&$firstHeaderProcessed) {
                    $element = $node->getNode(0);

                    // Create a new h3 element
                    $newElement = $element->ownerDocument->createElement('h3');

                    // Copy attributes from the old header element to the new h3 element
                    foreach ($element->attributes as $attribute) {
                        $newElement->setAttribute($attribute->name, $attribute->value);
                    }

                    // Add the 'fw-bold' class to the new h3 element
                    $existingClasses = $element->getAttribute('class');
                    $newClass = 'fw-bold';
                    $updatedClasses = ($existingClasses ? $existingClasses.' ' : '').$newClass;
                    $newElement->setAttribute('class', $updatedClasses);

                    // Move child nodes from the old header element to the new h3 element
                    while ($element->firstChild) {
                        $newElement->appendChild($element->firstChild);
                    }

                    // Replace the old header element with the new h3 element in the DOM
                    $element->parentNode->replaceChild($newElement, $element);

                    // Only for the first header
                    if (! $firstHeaderProcessed) {
                        $firstHeaderProcessed = true;

                        $nextSibling = $newElement->nextSibling;
                        while ($nextSibling) {
                            if ($nextSibling->nodeType === XML_ELEMENT_NODE) {
                                if ($nextSibling->nodeName === 'p' && ($nextSibling->getElementsByTagName('img')->length > 0 || $nextSibling->getElementsByTagName('figure')->length > 0)) {
                                    // Remove <p> if it contains an <img> or <figure> directly
                                    $nextSibling->parentNode->removeChild($nextSibling);
                                    break;
                                } elseif ($nextSibling->nodeName === 'img' || $nextSibling->nodeName === 'figure') {
                                    // Direct <img> or <figure> without wrapping <p>
                                    $newElement->parentNode->removeChild($nextSibling);
                                    break;
                                } else {
                                    break;
                                }
                            } else {
                                $nextSibling = $nextSibling->nextSibling;
                            }
                        }
                    }
                });

                // Modify the DOM by wrapping the <img> tags inside a <figure> and adding the desired structure
                $crawler->filter('img')->each(function (Crawler $node) {
                    $imgElement = $node->getNode(0);

                    // Update the class of the <img>
                    $existingClasses = $imgElement->getAttribute('class');
                    $newClasses = 'img-fluid rounded-2 shadow-sm mb-2';
                    $updatedClasses = ($existingClasses ? $existingClasses.' ' : '').$newClasses;
                    $imgElement->setAttribute('class', $updatedClasses);

                    // Create a new <figure> element
                    $figureElement = new \DOMElement('figure');
                    $imgElement->parentNode->insertBefore($figureElement, $imgElement);

                    // Move the <img> inside the <figure>
                    $figureElement->appendChild($imgElement);
                    $figureElement->setAttribute('class', 'image');

                    // Create a new <footer> element inside <figure>
                    $footerElement = new \DOMElement('footer', $imgElement->getAttribute('alt'));
                    $figureElement->appendChild($footerElement);
                    $footerElement->setAttribute('class', 'image-caption');
                });

                // Add Bootstrap 5 styling to tables
                $crawler->filter('table')->each(function (Crawler $node) {
                    $tableElement = $node->getNode(0);
                    $existingClasses = $tableElement->getAttribute('class');
                    $newClass = 'table';
                    $updatedClasses = ($existingClasses ? $existingClasses.' ' : '').$newClass;
                    $tableElement->setAttribute('class', $updatedClasses);
                });

                // Convert the modified DOM back to HTML
                $updatedHtml = '';
                foreach ($crawler as $domElement) {
                    $updatedHtml .= $domElement->ownerDocument->saveHTML($domElement);
                }

                return $updatedHtml;

            }

        }

        return '';

    }

    public function getFeaturedImageLqipAttribute()
    {
        $featuredImage = $this->featured_image;

        // Get the extension of the original featured image
        $extension = pathinfo($featuredImage, PATHINFO_EXTENSION);

        // Append "_lqip" before the extension to create the LQIP image URL
        return str_replace(".{$extension}", "_lqip.{$extension}", $featuredImage);
    }

    public function toFeedItem(): FeedItem
    {
        return FeedItem::create()
            ->id($this->id)
            ->title($this->title)
            ->summary($this->excerpt)
            ->updated($this->publish_date)
            ->link(route('home.country.post', ['country' => $this->post_category?->category?->country_locale_slug, 'post_slug' => $this->slug]))
            ->authorName($this->author->name);
    }

    public static function getFeedItems()
    {
        return Post::where('status', 'publish')->latest()->get();
    }
}
