<?php

namespace Modules\Seo\Controllers;

use App\Helpers\ApiClient;
use App\Http\Controllers\Services\PostService;
use GuzzleHttp\Client as GuzzleHttpClient;
use Illuminate\Http\Request;
use Modules\Seo\Models\User;
use Megaads\ApifyClient\Client;
use Modules\Seo\Models\Category;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;
use Modules\Seo\Controllers\Services\RssHelperService;
use Modules\Seo\Models\LandingPage;
use Modules\Seo\Models\TopSeller;
use Modules\Seo\Models\TrendingTag;

class RssController extends Controller
{
    protected $perPage = 5000;
    protected $cacheRssTagByPage = 'cache::rss::tags::tag-by-page_';
    protected $cacheRssShopByPage = 'cache::rss::shops::shop-by-page_';
    protected $guzzleHttpClient;
    protected $rssPath;
    protected $folderPath;
    protected $defaultSellerName;
    protected $totalItemDisplay;
    protected $postService;
    const PRODUCT_FILE_PREFIX = '_new_product_';

    public function __construct()
    {
        $this->cacheRssTagByPage = decorCacheKey($this->cacheRssTagByPage);
        $this->cacheRssShopByPage = decorCacheKey($this->cacheRssShopByPage);
        $this->guzzleHttpClient = new GuzzleHttpClient([
            'verify' => false,
        ]);
        $this->postService = new PostService();
        $this->rssPath = 'rss-files';
        $this->totalItemDisplay = 200;
        $this->folderPath = public_path($this->rssPath);
        $defaultSeller = User::where('email', config('sa.default_seller_email', 'info@megaads.vn'))->first();
        $this->defaultSellerName = $defaultSeller ? $defaultSeller->name : getOption('general.store_name', 'Printerval');

        $locale = env('APP_LOCALE');
        if (empty($locale)) $locale = 'us';
        $timezone = 'UTC';
        switch ($locale) {
            case 'us': $timezone = 'America/New_York'; break;
            case 'uk': $timezone = 'Europe/London'; break;
            case 'de': $timezone = 'Europe/Berlin'; break;
            case 'fr': $timezone = 'Europe/Paris'; break;
            case 'it': $timezone = 'Europe/Rome'; break;
            case 'es': $timezone = 'Europe/Madrid'; break;
            case 'pt': $timezone = 'Europe/Lisbon'; break;
            case 'ca': $timezone = 'America/Toronto'; break;
            case 'au': $timezone = 'Australia/Sydney'; break;
            case 'jp': $timezone = 'Asia/Tokyo'; break;
            case 'kr': $timezone = 'Asia/Seoul'; break;
            case 'vn': $timezone = 'Asia/Ho_Chi_Minh'; break;
        }
        date_default_timezone_set($timezone);
    }

    public function listRss(Request $request) {
        $locale = env('APP_LOCALE', '');
        set_time_limit(3600);

        $data = [
            'rss_categories' => $this->getCategoriesForRss(),
            'rss_tags' => $this->getTagsForRss(),
            'rss_pages' => $this->getLandingPagesForRss(),
            'rss_shops' => $this->getShopsForRss(),
            'rss_posts_categories' => $this->getPostsCategoriesForRss(),
            'rss_products' => []
        ];

        $pathFolder = public_path($this->rssPath);
        $fileInDirs = File::files($pathFolder);
        foreach ($fileInDirs as $fileName) {
            if (strpos($fileName, ($locale ? '_' . $locale : '') . self::PRODUCT_FILE_PREFIX) !== false) {
                array_push($data['rss_products'], str_replace([$pathFolder . '/', '.xml'], ['', ''], $fileName));
            }
        }
        
        return view('seo::rss.list-rss', $data);
    }

    public function checkExistsFolder($path) {
        if (file_exists($path)) {
            File::mkdir($path);
        }
    }

    public function showProductRss($slug) {
        $routeParameters = \Route::current()->parameters();
        $slug = $routeParameters['slug'];
        $xmlFilePath = public_path($this->rssPath . '/' . $slug . '.xml');
        ob_clean();
        return file_exists($xmlFilePath) ? response()->file($xmlFilePath, [ 'Content-Type' => 'application/xml' ]) : abort(404);
    }
    
    public function showHomeRss() {
        $locale = env('APP_LOCALE', '');
        $xmlFilePath = public_path($this->rssPath . '/rss' . ($locale ? '_' . $locale : '') . '_home.xml');
        ob_clean();
        return (file_exists($xmlFilePath)) ? response()->file($xmlFilePath, [ 'Content-Type' => 'application/xml' ]) : abort(404);
    }

    public function showCategoryRss($slug) {
        $routeParameters = \Route::current()->parameters();
        $slug = $routeParameters['slug'];
        $locale = env('APP_LOCALE', '');
        $path = $this->rssPath . '/rss' . ($locale ? '_' . $locale : '') . '_category_' . $slug . '.xml';
        $xmlFilePath = public_path($path);

        ob_clean();
        return (file_exists($xmlFilePath)) ? response()->file($xmlFilePath, [ 'Content-Type' => 'application/xml' ]) : abort(404);
    }

    public function showTagRss($slug) {
        $routeParameters = \Route::current()->parameters();
        $slug = $routeParameters['slug'];
        $locale = env('APP_LOCALE', '');
        $path = $this->rssPath . '/rss' . ($locale ? '_' . $locale : '') . '_tag_' . $slug . '.xml';
        $xmlFilePath = public_path($path);

        ob_clean();
        return (file_exists($xmlFilePath)) ? response()->file($xmlFilePath, [ 'Content-Type' => 'application/xml' ]) : abort(404);
    }

    public function showNewsRss($slug) {
        $routeParameters = \Route::current()->parameters();
        $slug = $routeParameters['slug'];
        $locale = env('APP_LOCALE', '');
        $path = $this->rssPath . '/rss' . ($locale ? '_' . $locale : '') . '_post_category_' . $slug . '.xml';
        $xmlFilePath = public_path($path);

        ob_clean();
        return (file_exists($xmlFilePath)) ? response()->file($xmlFilePath, [ 'Content-Type' => 'application/xml' ]) : abort(404);
    }

    public function showShopRss($slug) {
        $routeParameters = \Route::current()->parameters();
        $slug = $routeParameters['slug'];
        $locale = env('APP_LOCALE', '');
        $path = $this->rssPath . '/rss' . ($locale ? '_' . $locale : '') . '_shop_' . $slug . '.xml';
        $xmlFilePath = public_path($path);

        ob_clean();
        return (file_exists($xmlFilePath)) ? response()->file($xmlFilePath, [ 'Content-Type' => 'application/xml' ]) : abort(404);
    }

    public function showPageRss($slug) {
        $routeParameters = \Route::current()->parameters();
        $slug = $routeParameters['slug'];
        $locale = env('APP_LOCALE', '');
        $path = $this->rssPath . '/rss' . ($locale ? '_' . $locale : '') . '_page_' . $slug . '.xml';
        $xmlFilePath = public_path($path);

        ob_clean();
        return (file_exists($xmlFilePath)) ? response()->file($xmlFilePath, [ 'Content-Type' => 'application/xml' ]) : abort(404);
    }

    private function buildHomeRss($xmlFileName) {
        $products = $this->getDataProductForHome();
        $storeName = getOption('general.store_name');
        $language = config('seo::default.language', 'us');

        $channel = [
            'name' => $storeName,
            'title' => "Home RSS",
            'atomlink' => route('seo::rss::home'),
            'link' => route('home'),
            'build_date' => date('r', time()),
            'description' => htmlspecialchars('Home RSS', ENT_XML1 | ENT_COMPAT | ENT_QUOTES, 'UTF-8'),
            'language' => $language
        ];

        ob_clean();
        $xml = view('seo::rss/rss-template', [
            'data' => [
                'channel' => $channel,
                'items' => $this->buildItemsData($products, $storeName)
            ]
        ])->render();
        
        if (!File::exists($this->folderPath)) {
            File::makeDirectory($this->folderPath, 0777, true, true);
        }
        
        file_put_contents($xmlFileName, $xml);

        return $xml;
    }

    private function getDataProductForHome() {
        return DB::table(DB::raw('sb_product force index(primary)'))
        ->leftJoin(DB::raw('sb_product_n_user FORCE INDEX (pId)'), 'product_n_user.product_id', '=', 'product.id')
        ->leftJoin('users', 'users.id', '=', 'product_n_user.user_id')
        ->where('product.status', 'ACTIVE')
        ->whereNull('product.deleted_at')
        ->select([
            'product.id',
            'product.name',
            'product.slug',
            'product.description',
            'product.content',
            'product.image_url',
            'product.created_at',
            DB::raw("CASE WHEN COALESCE(sb_users.name, '') = '' THEN '{$this->defaultSellerName}' ELSE sb_users.name END AS creator_name")
        ])
        ->orderBy('product.id', 'desc')
        ->limit($this->totalItemDisplay)
        ->get()
        ->toArray();
    }

    private function buildChannelCategoryData($category, $storeName, $metaDataCategory) {
        $channel = [
            'name' => $storeName,
            'title' => htmlspecialchars($category->name, ENT_XML1 | ENT_COMPAT | ENT_QUOTES, 'UTF-8') . " RSS",
            'atomlink' => route('seo::rss::category', ['slug' => $category->slug]),
            'link' => route('seo::rss::category', ['slug' => $category->slug]),
            'build_date' => date('r', time()),
            'description' => htmlspecialchars($metaDataCategory['description'], ENT_XML1 | ENT_COMPAT | ENT_QUOTES, 'UTF-8'),
            'language' => config('seo::default.language', 'us')
        ];

        return $channel;
    }

    private function buildItemsData($products, $storeName) {
        $this->mapUsers($products);
        $ids = [];
        $items = [];
        $metaConfig = getOption('product');

        if(count($products) > 0) {
            foreach ($products as $item) {
                if (!in_array($item->id, $ids)) {
                    array_push($ids, $item->id);
    
                    $metaData = buildMetaConfigurationData('product', $metaConfig, [
                        'product_id' => $item->id,
                        'name' => $item->name,
                        'store_name' => $storeName,
                        'created_at' => $item->created_at,
                    ]);
    
                    $items[] = [
                        'title' => htmlspecialchars($item->name, ENT_XML1 | ENT_COMPAT | ENT_QUOTES, 'UTF-8'),
                        'link' => route('product', ['slug' => $item->slug, 'id' => $item->id]),
                        'comment_link' => route('product', ['slug' => $item->slug, 'id' => $item->id]) . '#moduleReviewForm',
                        'pub_date' => date('r', strtotime($item->created_at)),
                        'creator' => (isset($item->user->name))? $item->user->name : $this->defaultSellerName,
                        'description' => htmlspecialchars($metaData['description'], ENT_XML1 | ENT_COMPAT | ENT_QUOTES, 'UTF-8'),
                        'image_url' => getImageCdn($item->image_url, 960, 960),
                        'product_id' => $item->id,
                    ];
                }
            }
            $chunkedIds = array_chunk($ids, 100);
            $dataContent = [];
            foreach ($chunkedIds as $chunk) {
                $data = $this->getConfigContentProduct($chunk);
                $dataContent = array_merge($dataContent, $data);
            }
            foreach ($items as &$item) {
                $productId = $item['product_id'];
                $item['content'] = isset($dataContent[$productId]) ? $dataContent[$productId] : '';
            }
        }

        return $items;
    }

    private function buildCategory($categories, $storeName) {
        $locale = env('APP_LOCALE', '');
        $metaConfig = getOption('category');

        foreach ($categories as $category) {
            $xmlFilePath = public_path($this->rssPath . '/rss' . ($locale ? '_' . $locale : '') . '_category_' . $category->slug . '.xml');
            $metaDataCategory = buildMetaConfigurationData('category', $metaConfig, [ 'name_category' => $category->name ]);
    
            if (!$category) abort(404);
    
            $productIds = DB::table('product_n_category')
                            ->where('category_id', $category->id)
                            ->select('id','product_id')
                            ->orderBy('id', 'desc')
                            ->limit($this->totalItemDisplay)
                            ->get()
                            ->pluck('product_id')
                            ->toArray();

            $products = DB::table('product')
                            ->whereIn('id', $productIds)
                            ->where('status', 'ACTIVE')
                            ->whereNull('deleted_at')
                            ->select([
                                'id',
                                'name',
                                'slug',
                                'description',
                                'content',
                                'image_url',
                                'created_at'
                            ])
                            ->orderBy('id', 'desc')
                            ->limit($this->totalItemDisplay)
                            ->get();

            $channel = $this->buildChannelCategoryData($category, $storeName, $metaDataCategory);
    
            ob_clean();
            $xml = view('seo::rss/rss-template', [
                'data' => [
                    'channel' => $channel,
                    'items' => $this->buildItemsData($products, $storeName)
                ]
            ])->render();
    
            if (!File::exists($this->folderPath)) {
                File::makeDirectory($this->folderPath, 0777, true, true);
            }
    
            file_put_contents($xmlFilePath, $xml);
        }
    }

    private function buildTagsRss($tag, $xmlFilePath, $metaConfig, $storeName) {
        $metaData = buildMetaConfigurationData('tag', $metaConfig, [ 'name' => $tag->title ]);

        $channel = [
            'name' => $storeName,
            'title' => htmlspecialchars($tag->title, ENT_XML1 | ENT_COMPAT | ENT_QUOTES, 'UTF-8') . " RSS",
            'atomlink' => route('seo::rss::tag', ['slug' => $tag->slug]),
            'link' => route('categoryOrTag', ['slug' => $tag->slug]),
            'build_date' => date('r', time()),
            'description' => htmlspecialchars($metaData['description'], ENT_XML1 | ENT_COMPAT | ENT_QUOTES, 'UTF-8'),
            'language' => config('seo::default.language', 'us')
        ];


        // get tag_refer_id ~ product_id
        $tagReferIds = DB::table('tag_refer')
                            ->where('tag_id', $tag->id)
                            ->orderBy('id', 'desc')
                            ->limit($this->totalItemDisplay)
                            ->pluck('refer_id')
                            ->toArray();

        $products = DB::table(DB::raw('sb_product force index(PRIMARY)'))
                        ->where('product.status', 'ACTIVE')
                        ->whereIn('product.id', $tagReferIds)
                        ->whereNull('product.deleted_at')
                        ->select([
                            'product.id', 
                            'product.name', 
                            'product.slug', 
                            'product.description', 
                            'product.content',
                            'product.image_url',
                            'product.created_at'
                        ])
                        ->orderby('product.id', 'desc')
                        ->get();

        ob_clean();
        $xml = view('seo::rss/rss-template', [
                'data' => [
                    'channel' => $channel,
                    'items' => $this->buildItemsData($products, $storeName)
                ]
            ])->render();

        if (!File::exists($this->folderPath)) {
            File::makeDirectory($this->folderPath, 0777, true, true);
        }

        file_put_contents($xmlFilePath, $xml);
    }

    private function buildNewsRss($xmlFilePath, $storeName, $category){
        $metaConfig = getOption('post');
        $metaData = buildMetaConfigurationData('news', $metaConfig, []);
        $channel = [
            'name' => $storeName,
            'title' => htmlspecialchars($category->name, ENT_XML1 | ENT_COMPAT | ENT_QUOTES, 'UTF-8') . " RSS",
            'atomlink' => route('seo::rss::news', ['slug' => $category->slug]),
            'link' => route('archive', ['slug' => $category->slug, 'id' => $category->id]),
            'build_date' => date('r', time()),
            'description' => htmlspecialchars($metaData['description'], ENT_XML1 | ENT_COMPAT | ENT_QUOTES, 'UTF-8'),
            'language' => config('seo::default.language', 'us')
        ];

        $postByCategories = DB::table('post_n_category')
                                ->where('category_id', $category->id)
                                ->orderBy('post_id', 'DESC')
                                ->limit($this->totalItemDisplay)
                                ->get();
        $postIds = [-1];
        foreach ($postByCategories as $item) {
            array_push($postIds, $item->post_id);
        }

        $posts = DB::table('post')
                    ->whereIn('id', $postIds)
                    ->where('status', 'ACTIVE')
                    ->select([
                        'id', 
                        'name', 
                        'slug', 
                        'description', 
                        'content',
                        'image_url',
                        'created_at'
                    ])
                    ->orderBy('post.created_at', 'desc')
                    ->get();
        
        $items = [];
        foreach ($posts as $item) {
            $items[] = [
                'title' => htmlspecialchars($item->name, ENT_XML1 | ENT_COMPAT | ENT_QUOTES, 'UTF-8'),
                'link' => route('post', ['slug' => $item->slug, 'id' => $item->id]),
                'comment_link' => route('post', ['slug' => $item->slug, 'id' => $item->id]),
                'pub_date' => date('r', strtotime($item->created_at)),
                'creator' => getOption('general.store_name', 'Printerval'),
                'description' => htmlspecialchars($item->description, ENT_XML1 | ENT_COMPAT | ENT_QUOTES, 'UTF-8'),
                'image_url' => getImageCdn($item->image_url, 960, 960),
                'content' => $this->postService->buildTemplate((array) $item),
            ];
        }
        
        ob_clean();
        $xml = view('seo::rss/rss-template', [
                'data' => [
                    'channel' => $channel,
                    'items' => $items
                ]
            ])->render();

        if (!File::exists($this->folderPath)) {
            File::makeDirectory($this->folderPath, 0777, true, true);
        }

        file_put_contents($xmlFilePath, $xml);
    }

    private function buildShopRss($xmlFileName, $shop, $storeName) {
        $channel = [
            'name' => $storeName,
            'title' => htmlspecialchars($shop->name, ENT_XML1 | ENT_COMPAT | ENT_QUOTES, 'UTF-8') . " RSS",
            'atomlink' => route('seo::rss::shop', ['slug' => $shop->slug]),
            'link' => route('seller', ['slug' => $shop->slug, 'id' => $shop->id]),
            'build_date' => date('r', time()),
            'description' => htmlspecialchars(trans('Shop') . ' ' . $shop->name, ENT_XML1 | ENT_COMPAT | ENT_QUOTES, 'UTF-8'),
            'language' => config('seo::default.language', 'us')
        ];
        
        $productIds = DB::table('product_n_user')
        ->where('user_id', $shop->id)
        ->select('id','product_id')
        ->orderBy('id', 'desc')
        ->limit($this->totalItemDisplay)
        ->get()
        ->pluck('product_id')
        ->toArray();

        $products = DB::table('product')
            ->whereIn('id', $productIds)
            ->where('status', 'ACTIVE')
            ->whereNull('deleted_at')
            ->select([
                'id', 
                'name', 
                'slug', 
                'description', 
                'content',
                'image_url',
                'created_at'
            ])
            ->orderBy('id', 'desc')
            ->limit($this->totalItemDisplay)
            ->get();

        ob_clean();
        $xml = view('seo::rss/rss-template', [
                'data' => [
                    'channel' => $channel,
                    'items' => $this->buildItemsData($products, $storeName)
                ]
            ])->render();

        if (!File::exists($this->folderPath)) {
            File::makeDirectory($this->folderPath, 0777, true, true);
        }

        file_put_contents($xmlFileName, $xml);
    }
    
    private function buildProductRss($xmlFileName, $products, $storeName) {
        $language = config('seo::default.language', 'us');
        $channel = [
            'name' => $storeName,
            'title' => "Products RSS",
            'atomlink' => route('seo::rss::home'),
            'link' => route('home'),
            'build_date' => date('r', time()),
            'description' => htmlspecialchars('Products RSS', ENT_XML1 | ENT_COMPAT | ENT_QUOTES, 'UTF-8'),
            'language' => $language
        ];

        ob_clean();
        $xml = view('seo::rss/rss-template', [
                'data' => [
                    'channel' => $channel,
                    'items' => $this->buildItemsData($products, $storeName)
                ]
            ])->render();

        if (!File::exists($this->folderPath)) {
            File::makeDirectory($this->folderPath, 0777, true, true);
        }

        file_put_contents($xmlFileName, $xml);
    }

    private function buildPageRss($page, $storeName, $xmlFilePath) {
        
        $channel = [
            'name' => $storeName,
            'title' => htmlspecialchars($page->title, ENT_XML1 | ENT_COMPAT | ENT_QUOTES, 'UTF-8') . " RSS",
            'atomlink' => route('seo::rss::page', ['slug' => $page->slug]),
            'link' => route('landing-page::landing-page', ['slug' => $page->slug]),
            'build_date' => date('r', time()),
            'description' => htmlspecialchars(trans('Shop') . ' ' . $page->title, ENT_XML1 | ENT_COMPAT | ENT_QUOTES, 'UTF-8'),
            'language' => config('seo::default.language', 'us')
        ];

        $productDataInLandingPage = json_decode($page->config_value);
        $arrayProductId = [];

        foreach ($productDataInLandingPage as $block) {
            if(isset($block->data->type) && $block->data->type == 'product') {
                $arrayProductId = array_merge($arrayProductId, $block->data->list_item ?? []);
            }
        }

        $arrayProductId = array_unique($arrayProductId);
        $products = DB::table('product')
            ->whereIn('id', $arrayProductId)
            ->where('status', 'ACTIVE')
            ->whereNull('deleted_at')
            ->select([
                'id', 
                'name', 
                'slug', 
                'description', 
                'content',
                'status',
                'image_url',
                'created_at'
            ])
            ->orderBy('id', 'desc')
            ->limit($this->totalItemDisplay)
            ->get();

        ob_clean();
        $xml = view('seo::rss/rss-template', [
                'data' => [
                    'channel' => $channel,
                    'items' => $this->buildItemsData($products, $storeName)
                ]
            ])->render();

        if (!File::exists($this->folderPath)) {
            File::makeDirectory($this->folderPath, 0777, true, true);
        }

        file_put_contents($xmlFilePath, $xml);
    }

    private function mapUsers(&$products) {
        $productIds = [];
        foreach ($products as $product) {
            $productIds[$product->id] = $product->id;
        }
        $productIds = array_values($productIds);

        $users = DB::table('product_n_user')
            ->join('users', 'users.id', '=', 'product_n_user.user_id')
            ->whereIn('product_id', $productIds)
            ->select(['users.name', 'users.slug', 'users.id', 'product_n_user.product_id'])
            ->get()
            ->toArray();
        
        $userByIds= [];
        foreach ($users as $user) {
            $userByIds[$user->product_id] = $user;
        }

        foreach ($products as $product) {
            if(isset($userByIds[$product->id])) {
                $product->user = $userByIds[$product->id];
            }
        }
    }

    public function buildAllRss(Request $request) {
        set_time_limit(7200);
        ini_set('memory_limit', '2048M');

        $retVal = ['status' => 'successful'];
        $locale = env('APP_LOCALE', '');
        $targetInput = $request->input('target');
        $target = explode(',', $targetInput);
        $storeName = getOption('general.store_name');

        // build home
        $totalHome = 0;
        if (!$targetInput || in_array('home', $target)) {
            
            $xmlFileHome = public_path($this->rssPath . '/rss' . ($locale ? '_' . $locale : '') . '_home.xml');
            $this->buildHomeRss($xmlFileHome);
            $totalHome = 1;
        }

        // build categories
        $totalCategories = 0;
        if (!$targetInput || in_array('category', $target)) {
            $categories = $this->getCategoriesForRss();
            if (count($categories) > 0) {
                $arrayCategorySlugLv0 = [];
                $arrayCategorySlugLv1 = [];
                $arrayCategorySlugLv2 = [];

                foreach ($categories as $item) {
                    if ($item->slug && !in_array($item->slug, $arrayCategorySlugLv0)) {
                        $totalCategories++;
                        $arrayCategorySlugLv0[] = $item->slug;
                        if (isset($item->childCates) && count($item->childCates) > 0) {
                            foreach ($item->childCates as $i) {
                                if ($i->slug && !in_array($i->slug, $arrayCategorySlugLv1)) {
                                    $totalCategories++;
                                    $arrayCategorySlugLv1[] = $i->slug;
                                }
                                if (isset($i->childCates) && count($i->childCates) > 0) {
                                    foreach ($i->childCates as $a) {
                                        if ($a->slug  && !in_array($a->slug, $arrayCategorySlugLv2)) {
                                            $totalCategories++;
                                            $arrayCategorySlugLv2[] = $a->slug;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                if (count($arrayCategorySlugLv0) > 0) {
                    $this->buildListFileRSSCategory($arrayCategorySlugLv0, $storeName);
                }
                if (count($arrayCategorySlugLv1) > 0) {
                    $this->buildListFileRSSCategory($arrayCategorySlugLv1, $storeName);
                }
                if (count($arrayCategorySlugLv2) > 0) {
                    $this->buildListFileRSSCategory($arrayCategorySlugLv2, $storeName);
                }
            }
        }

        // build tags
        $totalTags = 0;
        if (!$targetInput || in_array('tag', $target)) {
            if ($request->has('slug')) {
                $tags = DB::table('tag')
                            ->where('slug', '=', $request->input('slug'))
                            ->select(['id', 'title', 'slug', 'description'])
                            ->get();
            } else {
                $tags = $this->getTagsForRss();
            }
            
            if (count($tags) > 0) {
                $metaConfig = getOption('tag');
                foreach ($tags as $tag) {
                    $totalTags++;
                    $xmlFilePath = public_path($this->rssPath . '/rss' . ($locale ? '_' . $locale : '') . '_tag_' . $tag->slug . '.xml');
                    $this->buildTagsRss($tag, $xmlFilePath, $metaConfig, $storeName);
                }
            }
        }

        // build pages
        $totalPages = 0;
        if (!$targetInput || in_array('page', $target)) {
            $pages = $this->getLandingPagesForRss();
            if (count($pages) > 0) {
                foreach ($pages as $item) {
                    $totalPages++;
                    $xmlFilePath = public_path($this->rssPath . '/rss' . ($locale ? '_' . $locale : '') . '_page_' . $item->slug . '.xml');
                    $this->buildPageRss($item, $storeName, $xmlFilePath);
                }
            }
        }

        // build shops
        $totalShops = 0;
        if (!$targetInput || in_array('shop', $target)) {
            $shops = $this->getShopsForRss();
            if (count($shops) > 0) {
                foreach ($shops as $shop) {
                    $totalShops++;
                    $xmlFileName = public_path($this->rssPath . '/rss' . ($locale ? '_' . $locale : '') . '_shop_' . $shop->seller_slug . '.xml');
                    $this->buildShopRss($xmlFileName, $shop, $storeName);
                }
            }
        }

        //build products new arrival
        $totalProductsNewArrival = 0;
        if (!$targetInput || in_array('product', $target)) {
            $products = $this->getProductForRss();
            $chunkItems = array_chunk($products->toArray(), $this->totalItemDisplay);
            if (count($chunkItems) > 0) {
                foreach ($chunkItems as $index => $items) {
                    $totalProductsNewArrival++;
                    $xmlFileName = public_path($this->rssPath . '/rss' . ($locale ? '_' . $locale : '') . self::PRODUCT_FILE_PREFIX . ($index + 1) . '.xml');
                    $this->buildProductRss($xmlFileName, $items, $storeName);
                }
            }
        }

        //build postsCategories
        $totalPostsCategories = 0;
        if (!$targetInput || in_array('posts-category', $target)) {
            $postsCategories = $this->getPostsCategoriesForRss();
            $postsCategorySlugs = [];
            if (count($postsCategories) > 0) {
                foreach ($postsCategories as $item) {
                    if ($item->slug && !in_array($item->slug, $postsCategorySlugs)) {
                        $totalPostsCategories++;
                        $postsCategorySlugs[] = $item->slug;
                    }
                }

                $categories = Category::whereIn('slug', $postsCategorySlugs)
                ->where('type', 'POST')
                ->select(['id', 'name', '_lft', '_rgt', 'depth', 'parent_id', 'type', 'slug', 'description'])
                ->get();
                
                foreach ($categories as $category) {
                    $xmlFilePath = $this->folderPath . '/rss' . ($locale ? '_' . $locale : '') . '_post_category_' . $category->slug . '.xml';
                    $this->buildNewsRss($xmlFilePath, $storeName, $category);
                }

                $this->buildAllNews($locale, $storeName);
            }
        }

        $retVal = [
            'status' => 'successful',
            'result' => [
                'count_home' => $totalHome,
                'count_categories' => $totalCategories,
                'count_tags' => $totalTags,
                'count_pages' => $totalPages,
                'count_shops' => $totalShops,
                'count_posts_category' => $totalPostsCategories,
                'count_products' => $totalProductsNewArrival
            ]
        ];

        return response()->json($retVal);
    }

    private function buildAllNews($locale, $storeName) {
        $xmlFilePath = $this->folderPath . '/rss' . ($locale ? '_' . $locale : '') . '_post_category_all-news.xml';
        $this->buildAllNewsRss($xmlFilePath, $storeName);
    }

    private function buildAllNewsRss($xmlFilePath, $storeName){
        $metaConfig = getOption('news');
        $metaData = buildMetaConfigurationData('news', $metaConfig, []);
        $channel = [
            'name' => $storeName,
            'title' => htmlspecialchars('News', ENT_XML1 | ENT_COMPAT | ENT_QUOTES, 'UTF-8') . " RSS",
            'atomlink' => route('seo::rss::news', ['slug' => 'news']),
            'link' => config('app.url') . "/rss/news/all-news.xml",
            'build_date' => date('r', time()),
            'description' => htmlspecialchars($metaData['description'], ENT_XML1 | ENT_COMPAT | ENT_QUOTES, 'UTF-8'),
            'language' => config('seo::default.language', 'us')
        ];

        $posts = DB::table('post')
            ->where('status', 'ACTIVE')
            ->select([
                'post.id', 
                'post.name', 
                'post.slug', 
                'post.description', 
                'post.content',
                'post.image_url',
                'post.created_at'
            ])
            ->orderBy('post.created_at', 'desc')
            ->limit($this->totalItemDisplay)
            ->get();
        
        $items = [];
        foreach ($posts as $item) {
            $items[] = [
                'title' => htmlspecialchars($item->name, ENT_XML1 | ENT_COMPAT | ENT_QUOTES, 'UTF-8'),
                'link' => route('post', ['slug' => $item->slug, 'id' => $item->id]),
                'comment_link' => route('post', ['slug' => $item->slug, 'id' => $item->id]),
                'pub_date' => date('r', strtotime($item->created_at)),
                'creator' => getOption('general.store_name', 'Printerval'),
                'description' => htmlspecialchars($item->description, ENT_XML1 | ENT_COMPAT | ENT_QUOTES, 'UTF-8'),
                'image_url' => getImageCdn($item->image_url, 960, 960),
                'content' => $this->postService->buildTemplate((array) $item),
            ];
        }
        
        ob_clean();
        $xml = view('seo::rss/rss-template', [
                'data' => [
                    'channel' => $channel,
                    'items' => $items
                ]
            ])->render();

        if (!File::exists($this->folderPath)) {
            File::makeDirectory($this->folderPath, 0777, true, true);
        }

        file_put_contents($xmlFilePath, $xml);
    }

    private function buildListFileRSSCategory($data, $storeName) {
        $categories = Category::whereIn('slug', array_unique($data))
            ->where('type', 'PRODUCT')
            ->select(['id', 'name', '_lft', '_rgt', 'depth', 'parent_id', 'type', 'slug', 'description'])
            ->get();

        $this->buildCategory($categories, $storeName);
    }

    public function getTagRssByCategory()
    {
        $routeParameters = \Route::current()->parameters();
        $categorySlug = $tagSlug = null;

        if (isset($routeParameters['category_slug'], $routeParameters['tag_slug'])) {
            $categorySlug = $routeParameters['category_slug'];
            $tagSlug = $routeParameters['tag_slug'];
        }

        $tag = DB::table('tag')->where('slug', $tagSlug)->first();
        $category = Category::where('slug', $categorySlug)
            ->where('type', 'PRODUCT')
            ->select(['id', 'name', 'slug', 'description'])
            ->first();

        if (!$tag || !$category) {
            return abort(404);
        }

        $filterData = [
            'id' => $category->id,
            'category_id' => $category->id,
            'category_slug' => $category->slug,
            'slug' => $tag->slug,
            'tag_id' => $tag->id,
            'page_type' => 'tag',
            'current_route_name' => 'tag',
            'is_tag_page' => true,
            'keyword' => $tag->title,
            'origin_keyword' => $tag->title,
            'page_size' => 20,
            'page_id' => 0
        ];

        $request = request();
        $request->merge([
            'dispatches_attrs' => [
                'category' => [
                    'id' => $category->id,
                    'target_id' => $category->id,
                    'type' => 'category',
                    'slug' => $category->slug,
                ],
                'tag' => [
                    'id' => $tag->id,
                    'target_id' => $tag->id,
                    'type' => 'tag',
                    'slug' => $tag->slug,
                ]
            ],
        ]);

        $products = app()->call('\Modules\ZSearch\Controllers\HomeController@getProductByFilter', [
            'keyword' => $tag->title,
            'dataFilter' => $filterData
        ]);
        
        $productAttachData = RssHelperService::getRssProductAttachData($products);

        $products = array_map(function($product) use ($productAttachData) {

            $productAttachItem = array_filter($productAttachData, function($prod) use ($product) {
                return $prod->id == $product['id'];
            });

            if (count($productAttachItem)) {

                $productAttachItem = end($productAttachItem);

                $product['created_at'] = $productAttachItem->created_at;
                $product['description'] = $productAttachItem->description;
                $product['content'] = $productAttachItem->content;
            }

            return $product;

        }, $products);

        $locale = env('APP_LOCALE', '');
        $storeName = getOption('general.store_name');

        $language = config('seo::default.language', 'us');

        $channel = [
            'name' => $storeName,
            'title' => htmlspecialchars($category->name, ENT_XML1 | ENT_COMPAT | ENT_QUOTES, 'UTF-8') . " RSS",
            'atomlink' => route('seo::rss::tag', ['slug' => $tag->slug]),
            'link' => route('seo::rss::tag_by_category', ['category' => $category->slug, 'tag' => $tag->slug]),
            'build_date' => date('r', time()),
            'description' => htmlspecialchars($category->description, ENT_XML1 | ENT_COMPAT | ENT_QUOTES, 'UTF-8'),
            'language' => $language
        ];

        $items = [];
        foreach ($products as $item) {
            $items[] = [
                'title' => htmlspecialchars($item['name'], ENT_XML1 | ENT_COMPAT | ENT_QUOTES, 'UTF-8'),
                'link' => route('product', ['slug' => $item['slug'], 'id' => $item['id']]),
                'comment_link' => route('product', ['slug' => $item['slug'], 'id' => $item['id']]) . '#moduleReviewForm',
                'pub_date' => (isset($item['created_at'])) ? date('r', strtotime($item['created_at'])) : date('r'),
                'creator' => (isset($item['user']['name']))? $item['user']['name'] : $this->defaultSellerName,
                'description' => htmlspecialchars(isset($item['description']) ? $item['description'] : '', ENT_XML1 | ENT_COMPAT | ENT_QUOTES, 'UTF-8'),
                'image_url' => $item['image_url'],
                'content' => isset($item['content']) ? $item['content'] : $item['content']
            ];
        }

        ob_clean();
        $xml = view('seo::rss/rss-template', [
            'data' => [
                'channel' => $channel,
                'items' => $items
            ]
        ])->render();

        header("Content-type: application/xml; charset=utf-8");
        echo $xml; exit();

    }

    private function getCategoriesForRss() {

        $categories = Category::with(["childCates"])
            ->select(['id', 'name', 'slug', 'parent_id'])
            ->where('type', 'PRODUCT')
            ->where('is_hidden', '!=', 1)
            ->whereNull('parent_id')
            ->get();

        $emptyCategoryIds = DB::table('empty_category')->pluck('category_id')->toArray();

        foreach ($categories as $key => &$category) {

            if (in_array($category->id, $emptyCategoryIds)) {
                $categories->forget($key);
                unset($categories[$key]);
                continue;
            }

            if (count($category->childCates)) {
                foreach ($category->childCates as $childKey => &$childCate) {

                    if (in_array($childCate->id, $emptyCategoryIds)) {
                        $category->childCates->forget($childKey);
                        unset($category->childCates[$childKey]);
                        continue;
                    }

                    $smallerCategories = $childCate
                        ->childCates()
                        ->select(['id', 'name', 'slug'])
                        ->whereNotIn('id', $emptyCategoryIds)
                        ->get();

                    if (count($smallerCategories) > 0) {
                        $childCate->smaller_categories = $smallerCategories;
                    }
                }
            }
        }

        return $categories;
    }

    protected function getPostsCategoriesForRss() {
        return DB::table('category')
                ->select(['category.id', 'category.name', 'category.slug'])
                ->join('post', 'post.category_id', '=', 'category.id')
                ->where('category.type', 'POST')
                ->where('post.status', 'active')
                ->groupBy('category.id')
                ->get();
    }

    protected function getLandingPagesForRss() {
        $landingPages = LandingPage::where('config_value', '!=', '')
            ->whereNotNull('config_value')
            ->whereNull('deleted_at')
            ->select('id', 'title', 'slug', 'config_value')
            ->get();

        return $landingPages;
    }

    protected function getTagsForRss() {
        return TrendingTag::join('tag', 'tag.id', '=','trending_tag.tag_id')
                        ->where('trending_tag.week_started_at', '>=', date('Y-m-d 00:00:00', strtotime('-2 week')))
                        ->select(['tag.id', 'tag.title', 'tag.slug', 'tag.description'])
                        ->orderBy('trending_tag.sale_count', 'DESC')
                        ->take(config('seo::default.rss.total_item_tag', 1000))
                        ->distinct()
                        ->get();
    }
    
    protected function getShopsForRss() {
        return TopSeller::orderBy('top_seller.created_at','ASC')
        ->join('users', 'users.id', '=', 'top_seller.seller_id')
        ->select(['top_seller.id', 'top_seller.seller_id', 'top_seller.seller_name', 'top_seller.seller_slug'])
        ->whereNotNull('top_seller.seller_slug')
        ->where('top_seller.seller_slug', '!=', '')
        ->take(config('seo::default.rss.total_item_top_seller', 500))
        ->get();
    }

    private function getProductForRss() {
        $products = DB::table('product')
                        ->where('status', 'ACTIVE')
                        ->whereNull('deleted_at')
                        ->select([
                            'id', 
                            'name', 
                            'slug', 
                            'description', 
                            'content',
                            'image_url',
                            'created_at'
                        ])
                        ->orderBy('id', 'desc')
                        ->limit($this->totalItemDisplay * 5)
                        ->get();

        return $products;
    }

    protected function getProductVariantDefaultData(array $ids): array
    {
        $retVal = [];
        $ids = implode(',', $ids);
        $response = $this->guzzleHttpClient->request("GET", "https://api.printerval.com/product/default-sku?get_category_merchant_id=0&ids={$ids}");
        $data = json_decode($response->getBody()->getContents());
        if(isset($data->status) && $data->status == 'successful') {
            $retVal = $data->result;
        }
        
        return $retVal;
    }
    
    private function getConfigContentProduct(array $ids)
    {
        $retVal = [];
        $result = $this->getProductVariantDefaultData($ids);
        $response = ApiClient::buildCustomRequest("product/get-list-product-by-ids?service_token=megaads@123", 'POST', ['ids' => $ids], []);

        foreach ($result as $item) {
            if (class_exists('Modules\ConfigDescription\Controllers\HomeController') && isset($response['status']) && $response['status'] == 'successful') {
                $dataResult = $response['result'];
                if ($dataResult[$item->id]) {
                    $data = $dataResult[$item->id];
                    $spid = $data['product']['variant_default']['id'] ?? null;
                    if (isset($data['product']['default_sku_id'])) {
                        $spid  = $data['product']['default_sku_id'];
                    }

                    if ($data['product']['id']) {
                        $input = [
                            'product_id' => $data['product']['id'],
                            'spid' => $spid,
                            'featureTag' => $data['feature_tag'],
                            'category' => $data['category'],
                            'variant_default' => $data['product']['variant_default'] ?? null
                        ];
                        
                        $configDescriptionController = new \Modules\ConfigDescription\Controllers\HomeController();
                        $description =  $configDescriptionController->getProductDescription($input);
                        $retVal[$item->id] = $description;
                    }
                }
            }
        }

        return $retVal;
    }

}