<?php

namespace Modules\Seo\Controllers;

use GuzzleHttp\Client;
use Illuminate\Http\Request;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Seo\Models\Category;
use Modules\Seo\Models\KeywordLink;
use Carbon\Carbon;

class AutoLinkController extends Controller
{
    public function runAutoLink(Request $request)
    {
        /* $id = $request->input('id');
        $keywordLink = KeywordLink::query()->where('id', $id)->first();
        $recordUpdated = 0;

        if ($keywordLink) {
            $keywordLink->is_processing = 2;
            $keywordLink->save();

            switch ($keywordLink->category_id) {
                case -1: $recordUpdated = $this->autoLinkProductFeatures($keywordLink); break; // product
                case -2: $recordUpdated = $this->autoLinkPosts($keywordLink); break; // post
            }

            $keywordLink->is_processing = null;
            $keywordLink->save();
        }

        return [
            'status' => 'success',
            'record_updated' => $recordUpdated
        ]; */
    }

    public function autoLinkProduct($productId, $content)
    {
        // find product categories
        $categories = [];
        $childCategory = DB::table('product_n_category')->where('product_id', $productId)
            ->join('category', 'category.id', 'product_n_category.category_id')
            ->where('is_parent', 0)
            ->select(['category.id', 'category._lft', 'category._rgt'])
            ->first();

        if ($childCategory) 
        {
            $categories = DB::table('category')
                ->orderBy('category._lft')
                ->where('is_hidden', 0)
                ->where('_lft', '<=', $childCategory->_lft)
                ->where('_rgt', '>=', $childCategory->_rgt)
                ->get([\DB::raw('distinct breadcrumb, `sb_category`.`id`, `sb_category`.`slug`, `sb_category`.`name`, `sb_category`.`_lft`')])
                ->toArray();

            $categories = array_map(function($cate) {
                return $cate->id;
            }, $categories);
        }

        // get all categories in autolink
        $autolinkCategories = DB::table('keyword_link')->select('category_id')->pluck('category_id')->toArray();
        // check $categories has any similar value with $autolinkCategories
        $hasSimilarValue = !empty(array_intersect($categories, $autolinkCategories));
        
        if (!$hasSimilarValue) return $content;

        // find auto keywords for this product
        $needApplyKeywords = DB::table('keyword_link_category')
            ->join('keyword_link', 'keyword_link.id', 'keyword_link_category.keyword_link_id')
            ->whereIn('keyword_link_category.category_id', $categories)
            ->where('keyword_link.status', 'enable')
            ->groupBy('keyword_link.id')
            ->orderBy('keyword_link.priority', 'desc')
            ->select('keyword_link.*')
            ->get();

        // all product keywords // temp ignore apply for all categories
        /* $allProductKeywords = DB::table('keyword_link')
            ->where('status', 'enable')
            ->where('category_id', -1)
            ->get();

        if ($allProductKeywords && count($allProductKeywords)) {
            if ($needApplyKeywords) {
                $needApplyKeywords = $needApplyKeywords->merge($allProductKeywords);
            } else {
                $needApplyKeywords = $allProductKeywords;
            }    
        } */

        // trigger auto keywords
        if ($needApplyKeywords && count($needApplyKeywords)) {

            // need optimize later
            for ($i = 0; $i < count($needApplyKeywords); $i++) {
                $content = $this->replaceKeywordLink((array) $needApplyKeywords[$i], $content);
            }
        }

        return $content;
    }

    public function autoLinkByCategory($categoryId, $content)
    {
        $category = DB::table('category')
            ->where('id', $categoryId)
            ->select(['category.id', 'category._lft', 'category._rgt'])
            ->first();

        if ($category) 
        {
            $categories = DB::table('category')
                ->orderBy('category._lft')
                ->where('is_hidden', 0)
                ->where('_lft', '>=', $category->_lft)
                ->where('_rgt', '<=', $category->_rgt)
                ->pluck('id')
                ->toArray();
        }

        // find auto keywords for this product
        $needApplyKeywords = DB::table('keyword_link_category')
            ->join('keyword_link', 'keyword_link.id', 'keyword_link_category.keyword_link_id')
            ->whereIn('keyword_link_category.category_id', $categories)
            ->where('keyword_link.status', 'enable')
            ->groupBy('keyword_link.id')
            ->orderBy('keyword_link.priority', 'desc')
            ->select('keyword_link.*')
            ->get();

        // all product keywords
        $allProductKeywords = DB::table('keyword_link')
            ->where('status', 'enable')
            ->where('category_id', -1)
            ->get();

        if ($allProductKeywords && count($allProductKeywords)) {
            if ($needApplyKeywords) {
                $needApplyKeywords = $needApplyKeywords->merge($allProductKeywords);
            } else {
                $needApplyKeywords = $allProductKeywords;
            }    
        }

        // trigger auto keywords
        if ($needApplyKeywords && count($needApplyKeywords)) {

            // need optimize later
            for ($i = 0; $i < count($needApplyKeywords); $i++) {
                $content = $this->replaceKeywordLink((array) $needApplyKeywords[$i], $content);
            }
        }

        return $content;
    }

    public function autoLinkPost($categoryIds, $content, $key = null)
    {
        // get cache
        if ($key && !isset($_GET['clear_cache'])) {

            // check cache
            // cache còn hạn không
            // hết hạn vẫn trả về cache nhưng gọi một async để update cache

            $autolinkContent = DB::table('autolink_content')->where('type', 'post')
                ->where('key', $key)
                ->first();

            $threeHoursAgo = Carbon::now()->subHours(3);

            if ($autolinkContent && $autolinkContent->updated_at >= $threeHoursAgo) {

                return $autolinkContent->content;

            } else {
                
                $triggerAutolinkUrl = $this->buildSiteUrl('/seo/autolink-v2/trigger');

                // call async update data
                $client = new Client();
                $promise = $client->postAsync($triggerAutolinkUrl, [
                    'form_params' => [
                        'type' => 'post',
                        'key' => $key,
                        'content' => $content,
                        'category_ids' => $categoryIds
                    ]
                ]);

                /* $promise->then(
                    function ($response) {
                        echo 'Response: ' . $response->getBody();
                    },
                    function ($exception) {
                        echo 'Error: ' . $exception->getMessage();
                    }
                );
                
                // Đợi cho đến khi yêu cầu hoàn thành nếu cần
                $promise->wait(); */

                if ($autolinkContent) {
                    return $autolinkContent->content;
                }

            }
            
        }
    
        // không có cache
        return $this->triggerAutoLinkPost($categoryIds, $content, $key);
    }

    public function triggerAutoLinkPost($categoryIds, $content, $key = null)
    {
        // find auto keywords for this product
        $needApplyKeywords = DB::table('keyword_link_category')
            ->join('keyword_link', 'keyword_link.id', 'keyword_link_category.keyword_link_id')
            ->whereIn('keyword_link_category.category_id', $categoryIds)
            ->where('keyword_link.status', 'enable')
            ->groupBy('keyword_link.id')
            ->orderBy('keyword_link.priority', 'desc')
            ->select('keyword_link.*')
            ->get();

        // all product keywords
        $allPostKeywords = DB::table('keyword_link')
            ->where('status', 'enable')
            ->where('category_id', -2)
            ->get();

        if ($allPostKeywords && count($allPostKeywords)) {
            if ($needApplyKeywords) {
                $needApplyKeywords = $needApplyKeywords->merge($allPostKeywords);
            } else {
                $needApplyKeywords = $allPostKeywords;
            }    
        }

        // trigger auto keywords
        if ($needApplyKeywords && count($needApplyKeywords)) {

            // need optimize later
            for ($i = 0; $i < count($needApplyKeywords); $i++) {
                $content = $this->replaceKeywordLink((array) $needApplyKeywords[$i], $content);
            }
        }
        
        // cache to database
        if ($key) {

            $autolinkContent = DB::table('autolink_content')->where('type', 'post')
                ->where('key', $key)
                ->first();

            if ($autolinkContent) {
                DB::table('autolink_content')->where('id', $autolinkContent->id)->update([
                    'content' => $content,
                    'updated_at' => date('Y-m-d H:i:s'),
                ]);
            } else {
                DB::table('autolink_content')->insert([
                    'key' => $key,
                    'type' => 'post',
                    'content' => $content
                ]);
            }

        }

        return $content;
    }

    public function autoLinkText($content, $categoryId)
    {
        // all keywords
        $needApplyKeywords = DB::table('keyword_link')
            ->where('status', 'enable')
            ->where('category_id', $categoryId)
            ->get();

        // trigger auto keywords
        if ($needApplyKeywords && count($needApplyKeywords)) {
            // need optimize later
            for ($i = 0; $i < count($needApplyKeywords); $i++) {
                $content = $this->replaceKeywordLink((array) $needApplyKeywords[$i], $content);
            }
        }

        return $content;
    }

    private function replaceKeywordLink($keywordLinkData, $content)
    {
        // $keywordLinkData = $keywordLink->toArray();
        $keywordLinkKeyword = preg_quote($keywordLinkData['keyword'], '/');
        $keyword = htmlentities($keywordLinkKeyword, ENT_QUOTES, 'UTF-8');
		
        $draft = $this->removeAutoKeywordLink($content, $keywordLinkData['id']);

        $numReplace = $keywordLinkData['auto']; // replace_count
        $countLink = $this->getCountKeywordLink($draft, $keywordLinkData['id']);

        $headingRegex = "/(<h.*?>)(.*?)(<\/h.*?>)/si";
        $draft = inSpecCharByRegex($draft, $headingRegex);

        // split heading tag for ignore 
        list($autoKeywords, $autoKeywordIds) = detectAutoKeywords($draft);

        // check priority ignoreKeywords, for replace
        $ignoreKeywords = [];
        $ignoreKeywordLinks = $this->getKeywordLinks($autoKeywordIds);

        for ($i = 0; $i < count($ignoreKeywordLinks); $i++) {
            if (isset($keywordLinkData['priority'], $ignoreKeywordLinks[$i]->priority) && $keywordLinkData['priority'] > $ignoreKeywordLinks[$i]->priority) {
                $draft = $this->removeAutoKeywordLink($draft, $ignoreKeywordLinks[$i]->id);
            } else {
                $ignoreKeywords[] = $ignoreKeywordLinks[$i]->keyword;
            }
        }

        // split a tag for ignore
        $aRegex = "/(<a\b[^>]*>)(.+?)(<\/a>)/si";
        $draft = inSpecCharByRegex($draft, $aRegex);

        if ($numReplace - $countLink > 0 && !in_array(strtolower($keywordLinkKeyword), $ignoreKeywords) && $keywordLinkData['status'] == "enable") 
        {
            $replaceString = "<a href=\"" . $keywordLinkData['link'] . "\" title=\"" . htmlentities($keywordLinkData['title']) . "\" data-keyword-link=\"" . $keywordLinkData['id'] . "\">$1</a>";

            try {
                $draft = str_replace('&#39;', '&#039;', $draft);
                $contentDraft = preg_replace("/(?!(?:[^<\[]+[>\]]|[^>\]]+<\/a>))\b(" . $keyword . ")\b/imsUu", $replaceString, $draft, $numReplace - $countLink, $countReplace);
                if ($numReplace - $countReplace > 0) {
                    $contentDraft = preg_replace("/(?!(?:[^<\[]+[>\]]|[^>\]]+<\/a>))\b(" . $keywordLinkData['keyword'] . ")\b/imsUu", $replaceString, $contentDraft, $numReplace - $countReplace);
                }
            } catch (\Exception $ex) {
                Log::info('error_auto_link', [$ex->getMessage() . ' line: ' . $ex->getLine() . ' keyword: ' . $keyword]);
                $contentDraft = $draft;
            }
        } else {
            $contentDraft = $draft;
        }

        $contentDraft = reSpecCharByRegex($contentDraft, $headingRegex);
        $contentDraft = reSpecCharByRegex($contentDraft, $aRegex);

        return stripslashes($contentDraft);
    }

    private function getKeywordLinks($ids = [])
    {
        return KeywordLink::whereIn('id', $ids)->get();
    }

    private function getCountKeywordLink($draft, $autoLinkId)
    {
        $retVal = 0;
        preg_match_all("/<a\b[^>]* data-keyword-link=\"$autoLinkId\">(.+?)<\/a>/is", $draft, $matches);
        if (isset($matches[1]) && count($matches[1]) > 0) {
            $listKeywordLinkId = array_unique($matches[1]);
            $retVal = count($listKeywordLinkId);
        }
        return $retVal;
    }

    private function removeAutoKeywordLink($content, $keywordLinkId)
    {
        $draft = preg_replace("/<a\b[^>]* data-keyword-link=\"" . $keywordLinkId . "\"[^>]*>(.+?)<\/a>/is", "$1", $content);
        return preg_replace("/<a\b[^>]* data-keyword-link='" . $keywordLinkId . "'[^>]*>(.+?)<\/a>/is", "$1", $draft);
    }

    private function buildSiteUrl($url) 
    {
        $locale = env('APP_LOCALE', 'us');
        if (!$locale) {
            $locale = 'us';
        }
        $baseUrl = env('APP_URL');
        if ($locale && $locale != config('localization::module.default_locale', 'us')) {
            $baseUrl .= '/' . $locale;
        }

        return $baseUrl . $url;
    }

    public function triggerAutoLink(Request $request)
    {
        $autolinkType = $request->input('type');

        switch ($autolinkType) {
            case 'post':

                $categoryIds = $request->input('category_ids');
                $content = $request->input('content');
                $key = $request->input('key');

                $this->triggerAutoLinkPost($categoryIds, $content, $key);

                break;
        }

        return [
            'status' => 'successfully'
        ];
    }

    public function testAutoFunction()
    {

        $categoryIds = [4, 64, 66];
        $content = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";;
        $key = '123';
    
        return $this->autolinkPost($categoryIds, $content, $key);

        die;

        $text  = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
        $text2 = "Lorem Ipsum is simply dummy <a href=\"https://example.com\" title=\"example title\" data-keyword-link=\"1\">text</a> of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
        $text3 = '<a href="https://example.com" title="example title" data-keyword-link="43">text</a> cái gì đó ở đây <br> <a href="https://example.com" title="example title" data-keyword-link="44">text</a>';

        $keywordLink = [
            'id' => 2,
            'keyword' => 'text',
            'link' => 'https://example.com',
            'title' => 'example title',
            'replace_count' => 1,
            'priority' => 2,
            'status' => 'enable'
        ];

        $this->replaceKeywordLink($keywordLink, $text3);

    }
    
}