<?php

namespace App\Services\Blog\Articles;

use App\Models\Article;
use App\Models\ArticleCategory;
use App\Models\ArticleTag;
use App\Models\Brand;
use App\Models\Setting;
use App\Models\Store;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;

class ArticlesService
{
    /** seo meta data */
    public array $seo = [
        'schema' => null,
        'site_name' => null,
        'title' => null,
        'store_name' => null,
        'description' => null,
        'keywords' => null,
        'canonical' => null,
        'author' => null,
        'image' => null,
        'type' => null,
    ];

    /** construct */
    public function __construct()
    {
        $blogName = Cache::remember('setting_blog_title', now()->addMonth(), function () {
            return Setting::where('key', 'blog_title')->first() != null ? Setting::where('key', 'blog_title')->first()->value : null;
        });

        // schema
        $this->seo['title'] = __('messages.sentence.articles_archive');

        // main
        $this->seo['site_name'] = $blogName;
    }

    /** get articles list */
    public function getArticles(Request $request)
    {
        /** @var LengthAwarePaginator */
        $articles = Article::query()->where('status', 'publish')
            // search
            ->when($request->input('search'), function ($query, $search) {
                $query->where('title', 'like', "%{$search}%");

                $this->seo['title'] = $search;
            })
            // filters
            ->when($request->input('latest'), function ($query, $latest) {
                if ($latest) {
                    $query->orderBy('created_at', 'desc');

                    $this->seo['title'] = __('messages.sentence.latest_articles');
                }
            })->when($request->input('most_viewed'), function ($query, $most_viewed) {
                if ($most_viewed) {
                    $query->orderBy('view_count', 'desc');

                    $this->seo['title'] = __('messages.sentence.most_viewed_articles');
                }
            })->when($request->input('popular'), function ($query, $popular) {
                if ($popular) {
                    $query->orderBy('vote', 'desc');

                    $this->seo['title'] = __('messages.sentence.popular_articles');
                }
            })->when($request->input('most_comment'), function ($query, $most_comment) {
                if ($most_comment) {
                    $query->withCount(['articleComments'])->orderBy('article_comments_count', 'desc');
                }
            })->when($request->input('editor_choice'), function ($query, $editor_choice) {
                if ($editor_choice) {
                    $query->where('editor_choice', true);

                    $this->seo['title'] = __('messages.sentence.editor_choice_articles');
                }
            })
            // lists
            ->when($request->input('random'), function ($query, $random) {
                if ($random) {
                    $query->inRandomOrder();
                }
            })
            // author
            ->when($request->input('profile'), function ($query, $profile) {
                $store = Store::where('status', 'active')->where('uuid', $profile)->first();
                if ($store != null) {
                    $query->where('user_id', $store->user->id);

                    // seo
                    $this->seo['title'] = $store->name;
                    $this->seo['description'] = $store->bio;
                    $this->seo['image'] = $store->get_logo;
                    $this->seo['type'] = 'author';
                } else {
                    $user = User::where('status', 'active')->where('username', $profile)->first();
                    if ($user != null) {
                        $query->where('user_id', $user->id);

                        // seo
                        $this->seo['title'] = $user->name;
                        $this->seo['description'] = $user->bio;
                        $this->seo['image'] = $user->get_avatar;
                        $this->seo['type'] = 'author';
                    }
                }
            })
            // tag
            ->when($request->input('tag'), function ($query, $tag) {
                $tag = ArticleTag::where('status', 'publish')->where('slug', $tag)->first();
                if ($tag != null) {
                    $query->whereHas('articleTags', function ($query) use ($tag) {
                        $query->where('slug', $tag->slug);
                    });

                    $tag->update([
                        'view_count' => $tag->view_count + 1
                    ]);

                    // seo
                    $this->seo['title'] = $tag->title;
                    $this->seo['type'] = 'tag';
                }
            })
            // brand
            ->when($request->input('brand'), function ($query, $brand) {
                $brand = Brand::where('slug', $brand)->first();
                if ($brand != null) {
                    $query->where('brand_id', $brand->id);

                    // seo
                    $this->seo['title'] = $brand->seo_title != null ? __('messages.word.brand') . ' ' . $brand->seo_title : __('messages.word.brand') . ' ' . $brand->title;
                    $this->seo['description'] = $brand->seo_description;
                    $this->seo['keywords'] = $brand->get_seo_keywords;
                    $this->seo['image'] = $brand->get_logo;
                    $this->seo['type'] = 'brand';
                }
            })
            // category
            ->when($request->input('cat'), function ($query, $cat) {
                $category = ArticleCategory::where('status', 'publish')->where('slug', $cat)->first();
                if ($category != null) {
                    $query->where('category_id', $category->id);

                    $category->update([
                        'view_count' => $category->view_count + 1
                    ]);

                    // seo
                    $this->seo['title'] = $category->seo_title != null ? $category->seo_title : $category->title;
                    $this->seo['description'] = $category->seo_description;
                    $this->seo['keywords'] = $category->get_seo_keywords;
                    $this->seo['image'] = $category->get_image;
                    $this->seo['type'] = 'category';
                }
            })
            // common
            ->orderBy('created_at', 'desc')->paginate(20)->through(fn($article) => [
                'id' => $article->id,
                'title' => $article->title,
                'slug' => $article->slug,
                'get_image' => $article->get_image,
                'editor_choice' => $article->editor_choice,
                'get_formatted_view_count' => $article->get_formatted_view_count,
                'jalali_created_at' => $article->jalali_created_at,

                'user' => $article->get_user,
                'category' => $article->get_category
            ]);

        $articles->withQueryString();


        // update seo title
        $blogName = Cache::remember('setting_blog_title', now()->addMonth(), function () {
            return Setting::where('key', 'blog_title')->first() != null ? Setting::where('key', 'blog_title')->first()->value : null;
        });
        $this->seo['title'] = $this->seo['title'] . ' - ' . $blogName;

        // handle schema
        $this->seo['schema'] = $this->articlesSchema($articles);

        return [
            'articles' => $articles,
            'seo' => $this->seo,
        ];
    }

    /** get keywords */
    public function getKeywords(Request $request)
    {
        /** keywords */
        $keywords = [
            'cat' => [
                'query' => null,
                'title' => null,
            ],
            'tag' => [
                'query' => null,
                'title' => null,
            ],
            'profile' => [
                'query' => null,
                'title' => null,
                'user' => null,
            ],
            'brand' => [
                'query' => null,
                'title' => null,
            ],
        ];

        if ($request->exists('cat') && $request->cat != null) {
            $category = ArticleCategory::where('status', 'publish')->where('slug', $request->cat)->first();
            if ($category != null) {
                $keywords['cat']['query'] = $request->cat;
                $keywords['cat']['title'] = $category->title;
            }
        } else if ($request->exists('tag') && $request->tag != null) {
            $tag = ArticleTag::where('status', 'publish')->where('slug', $request->tag)->first();
            if ($tag != null) {
                $keywords['tag']['query'] = $request->tag;
                $keywords['tag']['title'] = $tag->title;
            }
        } else if ($request->exists('profile') && $request->profile != null) {
            $store = Store::where('status', 'active')->where('uuid', $request->profile)->first();
            if ($store != null) {
                $keywords['profile']['query'] = $request->profile;
                $keywords['profile']['title'] = $store->name;
                $keywords['profile']['user'] = [
                    'id' => $store->user->id,
                    'username' => $store->user->username,
                    'get_name' => $store->user->get_name,
                    'bio' => $store->user->bio,
                    'get_avatar' => $store->user->get_avatar,
                    'type' => $store->user->type,
                    'role' => $store->user->role != null ? $store->user->role->label : null,
                    'articles_count' => $store->user->articles_count,
                    'get_social' => $store->user->get_social,
                    'jalali_created_at' => $store->user->jalali_created_at,
                    'seller' => $store->user->seller,
                    'store' => [
                        'id' => $store->id,
                        'uuid' => $store->uuid,
                        'name' => $store->name,
                        'bio' => $store->bio,
                        'get_logo' => $store->get_logo,
                    ]
                ];
            } else {
                $user = User::where('status', 'active')->where('username', $request->profile)->first();
                if ($user != null) {
                    $keywords['profile']['query'] = $request->profile;
                    $keywords['profile']['title'] = $user->get_name;
                    $keywords['profile']['user'] = $user->safe;
                }
            }
        } else if ($request->exists('brand') && $request->brand != null) {
            $brand = Brand::where('slug', $request->brand)->first();
            if ($brand != null) {
                $keywords['brand']['query'] = $request->brand;
                $keywords['brand']['title'] = $brand->title;
            }
        }

        return $keywords;
    }

    /** Product Schema */
    public function articlesSchema($articles)
    {
        $latestArticles = [];
        foreach ($articles as $key => $article) {
            $latestArticles[] = [
                "@type" => "ListItem",
                "position" => $key + 1,
                "name" => $article['title'],
                "url" => urldecode(route('blog.articles.show', $article['slug']))
            ];
        }

        $schema = [
            "@context" => "https://schema.org",
            "@type" => "ItemList",
            "url" => urldecode(route('blog.index')),
            "itemListElement" => $latestArticles
        ];

        return json_encode($schema, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    }
}
