<?php

namespace App\Models;

use App\Helpers\Image;

class Article extends AppModel
{
    protected $guarded = ['id'];

    /**
     * The attributes that should be cast to native types.
     *
     * @see https://laravel.com/docs/master/eloquent-mutators#attribute-casting
     *
     * @var array
     */
    protected $casts = [
        'user_id' => 'integer',
        'pay_type' => 'integer',
        'price' => 'double',
        'paid' => 'boolean',
        'disable_earnings' => 'boolean',
        'status' => 'integer',
        'hits' => 'integer',
        'tmp_content' => 'object',
        'seo' => 'array',
    ];

    /**
     * The attributes that should be mutated to dates.
     *
     * @see https://laravel.com/docs/master/eloquent-mutators#date-mutators
     *
     * @var array
     */
    protected $dates = [
        'created_at',
        'updated_at',
        'published_at',
    ];

    protected $perPage = 20;

    public function featuredImage()
    {
        return $this->belongsTo(File::class, 'featured_image_id')->withDefault();
    }

    public function user()
    {
        return $this->belongsTo(User::class)->withDefault();
    }

    public function tags()
    {
        return $this->belongsToMany(Tag::class);
    }

    public function categories()
    {
        return $this->belongsToMany(Category::class)->withPivot('main');
    }

    public function comments()
    {
        return $this->hasMany(Comment::class)->whereNull('parent_id');
    }

    public function activeComments()
    {
        return $this->comments()->where('status', 1)->orderBy('id')->get();
    }

    public function statistics()
    {
        return $this->hasMany(Statistic::class);
    }

    public function bookmarks(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
    {
        return $this->belongsToMany(User::class, 'bookmarks', 'article_id', 'user_id');
    }

    public function likes(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
    {
        return $this->belongsToMany(User::class, 'likes', 'article_id', 'user_id');
    }

    public function paidViews()
    {
        return $this->statistics()->where('statistics.reason', 1)->count();
    }

    public function mainCategory()
    {
        return $this->belongsToMany(Category::class)->wherePivot('main', 1);
        //return $this->belongsTo(Category::class, 'main_category_id')->withDefault();
    }

    /**
     * @return \App\Models\Category
     */
    public function getMainCategory()
    {
        if ($this->mainCategory->first()) {
            return $this->mainCategory->first();
        }

        return (new Category);
    }

    /**
     * @param int $count
     * @return AppModel[]|Article[]|\Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection|\Illuminate\Database\Query\Builder[]|\Illuminate\Support\Collection|null
     */
    public function relatedArticles($count = 6)
    {
        $tags = $this->tags->pluck('id')->toArray();
        $tags = array_filter($tags);

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

        $articles = self::query()
            ->with(['user', 'featuredImage', 'mainCategory'])
            ->whereHas('tags', function ($query) use ($tags) {
                /**
                 * @var \Illuminate\Database\Eloquent\Builder $query
                 */
                $query->whereIn('id', $tags);
                $query->where('status', 1);
            }
            )
            ->where('id', '!=', $this->id)
            ->orderBy('published_at', 'desc')
            ->whereIn('status', [1, 4])
            ->limit($count)
            ->get();

        return $articles;
    }

    /**
     * @param array $args
     *      'cats'     => '',
     *      'tags'     => '',
     *      'per_page' => 6,
     *      'order_by' => 'published_at',
     *      'order'    => 'desc',
     *      'page'     => '',
     *
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator|\App\Models\Article[]
     */
    public static function getArticles(array $args = [])
    {
        $type = $args['type'];

        if ($type === 'recent') {
            $query = self::query()
                ->has('mainCategory')
                ->with(['user', 'featuredImage', 'mainCategory'])
                ->whereIn('status', [1, 4])
                ->when((isset($args['cats']) && trim($args['cats'])), function ($query) use ($args) {
                    return $query->whereHas('categories', function ($query) use ($args) {
                        /**
                         * @var \Illuminate\Database\Eloquent\Builder $query
                         */
                        $cats = array_map(
                            function ($value) {
                                return (int)trim($value);
                            },
                            explode(',', $args['cats'])
                        );

                        $cats = array_filter($cats);

                        if (!empty($cats)) {
                            $query->whereIn('categories.id', $cats);
                            $query->where('categories.status', 1);
                        }
                    }
                    );
                })
                ->when((isset($args['tags']) && trim($args['tags'])), function ($query) use ($args) {
                    return $query->whereHas('tags', function ($query) use ($args) {
                        /**
                         * @var \Illuminate\Database\Eloquent\Builder $query
                         */
                        $tags = array_map(
                            function ($value) {
                                return (int)trim($value);
                            },
                            explode(',', $args['tags'])
                        );

                        $tags = array_filter($tags);

                        if (!empty($tags)) {
                            $query->whereIn('tags.id', $tags);
                            $query->where('tags.status', 1);
                        }
                    }
                    );
                })
                ->orderBy($args['order_by'], $args['order'])
                ->paginate($args['per_page']);

            return $query;
        }

        if ($type === 'popular') {
            $query = self::query()
                ->has('mainCategory')
                ->with(['user', 'featuredImage', 'mainCategory'])
                ->whereIn('status', [1, 4])
                ->withCount('statistics')
                ->when((isset($args['cats']) && trim($args['cats'])), function ($query) use ($args) {
                    return $query->whereHas('categories', function ($query) use ($args) {
                        /**
                         * @var \Illuminate\Database\Eloquent\Builder $query
                         */
                        $cats = array_map(
                            function ($value) {
                                return (int)trim($value);
                            },
                            explode(',', $args['cats'])
                        );

                        $cats = array_filter($cats);

                        if (!empty($cats)) {
                            $query->whereIn('categories.id', $cats);
                            $query->where('categories.status', 1);
                        }
                    }
                    );
                })
                ->when((isset($args['tags']) && trim($args['tags'])), function ($query) use ($args) {
                    return $query->whereHas('tags', function ($query) use ($args) {
                        /**
                         * @var \Illuminate\Database\Eloquent\Builder $query
                         */
                        $tags = array_map(
                            function ($value) {
                                return (int)trim($value);
                            },
                            explode(',', $args['tags'])
                        );

                        $tags = array_filter($tags);

                        if (!empty($tags)) {
                            $query->whereIn('tags.id', $tags);
                            $query->where('tags.status', 1);
                        }
                    }
                    );
                })
                ->orderByDesc('statistics_count')
                ->paginate($args['per_page']);

            return $query;
        }
    }

    public function permalink()
    {
        return route('article.show', ['slug' => $this->slug, 'article' => $this->id]);
        //return url("/{$this->slug}-{$this->id}") ;
    }

    public function getFinalContent()
    {
        static $finalContent = null;

        if (!$finalContent) {
            return \applyShortCodes($this->insertAdAfterParagraph($this->content));
        }

        return $finalContent;
    }

    protected function insertAdAfterParagraph($content)
    {
        $article_ads = get_style('ads_article_paragraphs', []);

        $ads = [];

        if (count($article_ads)) {
            foreach ($article_ads as $article_ad) {
                $p = (int)$article_ad['p'];
                $code = (int)$article_ad['code'];

                if ($p > 0 && $code > 0) {
                    $ads[] = [
                        'p' => $p,
                        'code' => \applyShortCodes('[ads id="' . $code . '"]'),
                    ];
                }
            }
        }

        if (!count($ads)) {
            return $content;
        }

        $closing_p = '</p>';
        $paragraphs = explode($closing_p, $content);
        foreach ($paragraphs as $index => $paragraph) {
            $paragraphs[$index] .= $closing_p;

            foreach ($ads as $ad) {
                if ($ad['p'] === $index + 1) {
                    $paragraphs[$index] .= $ad['code'];
                }
            }
            /*
            if ($paragraph_id === $index + 1) {
                $paragraphs[$index] .= $insertion;
            }
            */
        }

        return implode('', $paragraphs);
    }

    public function tagsString()
    {
        $tags = $this->tags;

        $string = '';

        foreach ($tags as $tag) {
            $string .= '<a class="badge badge-pill badge-light" href="' . $tag->permalink() . '">' .
                $tag->name . '</a>';
        }

        return $string;
    }

    public function getMainImage($size = null)
    {
        $image = (string)$this->featuredImage->file;
        if (!$image) {
            return asset('assets/img/thumb.png');
        }

        $extension = (string)$this->featuredImage->extension;

        if (!$size) {
            return asset($image);
        }

        $sizes = Image::$sizes;

        $size = $sizes[$size] ?? $sizes['medium'];

        $pattern = "/(.*?)" . preg_quote('.' . $extension, '/') . "$/"; // Ex. .jpg
        $replacement = "$1-{$size[0]}x{$size[1]}.{$extension}";

        $image = preg_replace($pattern, $replacement, $image);

        return asset($image);
    }

    public function getMainImageHTML($size = null)
    {
        $src = (string)$this->featuredImage->file;

        /*
        $meta = $this->featuredImage->meta;

        $srcset = '';
        if (!empty($meta['sizes'])) {
            foreach ($meta['sizes'] as &$meta_size) {
                $w_h = $meta_size;

                $meta_size = asset(
                    str_replace(
                        ".",
                        "-{$w_h[0]}x{$w_h[1]}.",
                        $src
                    )
                );
                $meta_size .= ' ' . $w_h[0] . 'w';
            }
            $srcset .= 'srcset="';
            $srcset .= implode(', ', $meta['sizes']);
            $srcset .= '"';
        }
        */

        /*
        $image_info = pathinfo(public_path($src));

        $images = @glob($image_info['dirname'] . DS . $image_info['filename'] . "-*." . $image_info['extension']);

        foreach ($images as &$image) {
            $image = str_replace(public_path(), '', $image);
            if (preg_match("/-(?<width>\d+)x(?<height>\d+)./", $image, $matches)) {
                $image = asset($image) . ' ' . $matches['width'] . 'w';
            };
        }

        $srcset = 'srcset="';
        $srcset .= implode(', ', $images);
        $srcset .= '"';
        */

        if (is_integer($size)) {
            $size = [$size, $size];
        }

        if (is_array($size)) {
            $src = str_replace(".", "-{$size[0]}x{$size[1]}.", $src);
        }

        if (empty($src)) {
            $src = "//via.placeholder.com/{$size[0]}x{$size[1]}";
        }

        $html = '<img src ="' . asset($src) . '" alt="' . e($this->title) . '" width="' . $size[0] . '" ' .
            'height="' . $size[1] . '" />';

        return $html;
    }

    public function getMainImageBackground()
    {
        $html = "background-image: url('" . $this->getMainImage([370, 222]) . "');" .
            "background-image: -webkit-image-set(url('" . $this->getMainImage([370, 222]) . "') 1x," .
            "url('" . $this->getMainImage([740, 444]) . "') 2x);" .
            "background-image: -moz-image-set(url('" . $this->getMainImage([370, 222]) . "') 1x," .
            "url('" . $this->getMainImage([740, 444]) . "') 2x);" .
            "background-image: -o-image-set(url('" . $this->getMainImage([370, 222]) . "') 1x," .
            "url('" . $this->getMainImage([740, 444]) . "') 2x);" .
            "background-image: -ms-image-set(url('" . $this->getMainImage([370, 222]) . "') 1x," .
            "url('" . $this->getMainImage([740, 444]) . "') 2x);";

        $html = str_replace(["\r\n", "\r", "\n", "\t"], '', $html);

        return $html;
    }

    public function getMainImageRatio($ratio)
    {
        /*
        $src = (string)$this->featuredImage->file;

        $image_info = pathinfo(public_path($src));

        $images = @glob($image_info['dirname'] . DS . $image_info['filename'] . "-*." . $image_info['extension']);

        foreach ($images as &$image) {
            $image = str_replace(public_path(), '', $image);
            if (preg_match("/-(?<width>\d+)x(?<height>\d+)./", $image, $matches)) {
                $image = asset($image) . ' ' . $matches['width'] . 'w';
            };
        }

        return $image;
        */
    }

    public function getSummary($length = null)
    {
        $summary = $this->summary;

        return $this->getTextWords($summary, $length);
    }

    public function getMetaDescription()
    {
        $summary = $this->summary;

        return $this->getTextChars($summary, 160);
    }
}
