<?php

namespace App\Http\Controllers;

use App\CategoryDetail;
use App\Events\NotifyEvent;
use App\Gutenberg;
use App\Helpers\Helper;
use App\Keyword;
use App\KeywordDetail;
use App\Notify;
use Carbon\Carbon;
use Illuminate\Http\Request;
use App\Article;
use Illuminate\Support\Arr;
use App\Http\Resources\ArticleResource;
use Illuminate\Support\Facades\Cache;
use Validator;
use Auth;

class ArticleController extends Controller
{
    const ITEM_PER_PAGE = 10;
    private $_postType = 'article';

    public function __construct(Request $request)
    {
        $this->_postType = Arr::get($request->all(), 'type', 'article');
    }

    public function index(Request $request)
    {
        $params = $request->all();
        $limit = Arr::get($params, 'limit', static::ITEM_PER_PAGE);
        $keyword = Arr::get($params, 'keyword', '');
        $categoryId = Arr::get($params, 'category', '');
        $tagId = Arr::get($params, 'tag', '');

        $list = Article::select('id', 'title', 'slug', 'thumbnail', 'publish_at', 'description')
            ->where('type', $this->_postType)
            ->where('is_activated', true)
            ->where('is_deleted', false);

        if ($categoryId != null && $categoryId != "") {
            $articleIds = CategoryDetail::select('id', 'article_id')->where('category_id', $categoryId)->pluck('article_id')->toArray();
            $list->whereIn('id', $articleIds);
        }

        if ($tagId != null && $tagId != "") {
            $tagIds = KeywordDetail::select('id', 'ref_id')
                ->where('type', 'article')
                ->where('keyword_id', $tagId)
                ->pluck('ref_id')
                ->toArray();
            $list->whereIn('id', $tagIds);
        }

        if ($keyword != null && $keyword != "") {
            $keywordItem = Keyword::where('is_deleted', 0)
                ->where(function ($query) use ($keyword) {
                    $query->where('name', $keyword)
                        ->orWhere('name', strtolower($keyword))
                        ->orWhere('name', strtoupper($keyword))
                        ->orWhere('name', ucfirst($keyword));
                })->first();

            $listDetailKeyword = [];
            if (isset($keywordItem) && $keywordItem->id != null) {
                $listDetailKeyword = KeywordDetail::select('ref_id')
                    ->where('keyword_id', $keywordItem->id)
                    ->where('type', 'article')
                    ->pluck('ref_id')
                    ->toArray();
            }

            $list = $list->where(function ($query) use ($keyword, $listDetailKeyword) {
                $query->where('title', 'like', "%$keyword%")
                    ->orWhere('description', 'like', "%$keyword%")
                    ->orWhereIn('id', $listDetailKeyword);
            });
        }
        $list = $list->orderBy('created_at', 'DESC');

        return ArticleResource::collection($list->paginate($limit));
    }

    public function recent(Request $request)
    {
        $params = $request->all();
        $limit = Arr::get($params, 'limit', static::ITEM_PER_PAGE);
        $list = Article::select('id', 'title', 'slug', 'thumbnail', 'publish_at')
            ->where('type', $this->_postType)
            ->where('is_activated', true)
            ->where('is_deleted', false)
            ->orderBy('created_at', 'DESC');

        return ArticleResource::collection($list->paginate($limit));
    }

    public function ranking(Request $request)
    {
        $params = $request->all();
        $limit = Arr::get($params, 'limit', static::ITEM_PER_PAGE);
        $list = Article::select('id', 'title', 'slug', 'thumbnail', 'publish_at')
            ->where('type', $this->_postType)
            ->where('is_activated', true)
            ->where('is_deleted', false)
            ->orderBy('important', 'DESC')
            ->orderBy('view_number', 'DESC')
            ->orderBy('created_at', 'DESC');

        return ArticleResource::collection($list->paginate($limit));
    }

    public function rankingList(Request $request)
    {
        $params = $request->all();
        $limit = Arr::get($params, 'limit', static::ITEM_PER_PAGE);

        $year = Article::select('id', 'title', 'slug', 'thumbnail', 'publish_at')
            ->where('type', $this->_postType)
            ->where('is_activated', true)
            ->where('is_deleted', false)
            ->orderBy('important', 'DESC')
            ->orderBy('view_number', 'DESC')
            ->orderBy('created_at', 'DESC')
            ->paginate($limit);

        $month = Article::select('id', 'title', 'slug', 'thumbnail', 'publish_at')
            ->where('type', $this->_postType)
            ->where('is_activated', true)
            ->where('is_deleted', false)
            ->orderBy('id', 'ASC')->paginate($limit);

        $week = Article::select('id', 'title', 'slug', 'thumbnail', 'publish_at')
            ->where('type', $this->_postType)
            ->where('is_activated', true)
            ->where('is_deleted', false)
            ->orderBy('important', 'DESC')
            ->orderBy('created_at', 'ASC')
            ->paginate($limit);

        return response()->json(['year' => $year, 'month' => $month, 'week' => $week], 200);
    }

    public function featureRecent(Request $request)
    {
        $params = $request->all();
        $limit = Arr::get($params, 'limit', static::ITEM_PER_PAGE);
        $list = Article::select('id', 'title', 'slug', 'description', 'thumbnail', 'content', 'publish_at')
            ->where('type', $this->_postType)
            ->where('is_activated', true)
            ->where('is_deleted', false)
            ->orderBy('created_at', 'DESC')
            ->limit($limit)
            ->get();

        return response()->json(['data' => $list], 200);
    }

    public function hot(Request $request)
    {
        $params = $request->all();
        $limit = Arr::get($params, 'limit', static::ITEM_PER_PAGE);
        $list = Article::select('id', 'title', 'slug', 'thumbnail', 'description', 'publish_at')
            ->where('type', $this->_postType)
            ->where('is_activated', true)
            ->where('is_deleted', false)
            ->orderBy('important', 'DESC')
            ->orderBy('created_at', 'DESC');

        return ArticleResource::collection($list->paginate($limit));
    }

    private function contentBetweenTags($content, $tagname)
    {
        $pattern = "#<\s*?$tagname\b[^>]*>(.*?)</$tagname\b[^>]*>#s";
        preg_match($pattern, $content, $matches);

        if (empty($matches)) return "";

        $str = "<$tagname>" . html_entity_decode($matches[1]) . "</$tagname>";
        return $str;
    }

    public function show(Request $request, $id = '')
    {
        $preview = '';
        if ($request->has('preview') && $request->get('preview') != "" && $request->get('preview') != null && $request->get('preview') != "null") $preview = $request->get('preview');

        /*$article = Article::with('category_detail')->select('articles.slug', 'articles.title', 'articles.description', 'articles.content', 'articles.gu_content', 'articles.keyword', 'articles.important', 'articles.thumbnail', 'articles.type', 'articles.publish_at', 'users.full_name as user_full_name', 'users.address as user_address', 'users.gender as user_gender')
            ->join('users', 'articles.user_id', '=', 'users.id')
            ->where('articles.type', $this->_postType)
            ->where('articles.is_deleted', false)
            ->where('articles.id', $id);

        if ($preview != "" && $preview != null) {
            $article->where('articles.preview', $preview);
        } else {
            $article->where('articles.is_activated', true);
        }*/

        $article = Article::with('user', 'author', 'category_detail')
            ->select('id', 'slug', 'title', 'description', 'content', 'gu_content', 'keyword', 'important', 'thumbnail', 'type', 'publish_at', 'created_by', 'user_id')
            ->where('type', $this->_postType)
            ->where('is_deleted', false)
            ->where('id', $id);

        if ($preview != "" && $preview != null) {
            $article->where('preview', $preview);
        } else {
            $article->where('is_activated', true);
        }

        return response()->json(['data' => $article->first()], 200);
    }

    public function questionPost(Request $request)
    {
        $params = $request->all();
        $limit = Arr::get($params, 'limit', static::ITEM_PER_PAGE);
        $keyword = Arr::get($params, 'keyword', '');

        $list = Article::select('id', 'title', 'slug', 'thumbnail', 'description', 'content', 'question_status', 'is_activated', 'publish_at')
            ->where('type', $this->_postType)
            ->where('user_id', auth('api')->user()->id)
            ->where('is_deleted', false);

        if ($keyword != null && $keyword != "") {
            $keywordItem = Keyword::where('is_deleted', 0)
                ->where(function ($query) use ($keyword) {
                    $query->where('name', $keyword)
                        ->orWhere('name', strtolower($keyword))
                        ->orWhere('name', strtoupper($keyword))
                        ->orWhere('name', ucfirst($keyword));
                })->first();

            $listDetailKeyword = [];
            if (isset($keywordItem) && $keywordItem->id != null) {
                $listDetailKeyword = KeywordDetail::select('ref_id')
                    ->where('keyword_id', $keywordItem->id)
                    ->where('type', 'article')
                    ->pluck('ref_id')
                    ->toArray();
            }

            $list = $list->where(function ($query) use ($keyword, $listDetailKeyword) {
                $query->where('title', 'like', "%$keyword%")
                    ->orWhere('description', 'like', "%$keyword%")
                    ->orWhereIn('id', $listDetailKeyword);
            });
        }
        $list = $list->orderBy('created_at', 'DESC');

        return ArticleResource::collection($list->paginate($limit));
    }

    public function showBySlug(Request $request, $slug = '')
    {
        $preview = '';
        if ($request->has('preview') && $request->get('preview') != "" && $request->get('preview') != null && $request->get('preview') != "null") $preview = $request->get('preview');

        $cacheKey = "article_show_" . str_replace("-", "_", trim($slug));
        if ($preview != "" && $preview != null) {
            $list = Cache::remember($cacheKey . "_" . $preview, (7 * 24 * 60 * 60), function () use ($slug, $preview) {
                $article = Article::select('slug', 'title', 'description', 'content', 'keyword', 'important', 'thumbnail', 'type', 'publish_at')
                    ->where('type', $this->_postType)
                    ->where('is_deleted', false)
                    ->where('slug', $slug)
                    ->where('preview', $preview)
                    ->first();
                return ['item' => $article, 'lastModify' => (gmdate('D, d M Y H:i:s') . ' GMT')];
            });
        } else {
            $list = Cache::remember($cacheKey, (7 * 24 * 60 * 60), function () use ($slug) {
                $article = Article::select('slug', 'title', 'description', 'content', 'keyword', 'important', 'thumbnail', 'type', 'publish_at')
                    ->where('type', $this->_postType)
                    ->where('is_deleted', false)
                    ->where('is_activated', true)
                    ->where('slug', $slug)
                    ->first();
                return ['item' => $article, 'lastModify' => (gmdate('D, d M Y H:i:s') . ' GMT')];
            });
        }

        return response()->json(['data' => $list['item'], 'relate' => [], 'ranking' => []], 200);
    }

    private function gutenbergRenderContent($content)
    {
        $renderContent = $content;
        try {
            $gutenberg = new Gutenberg();
            $gutenberg->lb_content = $content;
            $gutenberg->save();
            $renderContent = $gutenberg->lb_content;
            //$renderContent = $gutenberg->lb_raw_content;
            $gutenberg->delete();
        } catch (\Exception $exception) {
            logger($exception->getMessage());
        }

        return $renderContent;
    }

    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), ['category' => ['required'], 'title' => ['required'], 'content' => ['required']]);
        if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
        $params = $request->all();
        $publishAt = (isset($params['publish_at']) && $params['publish_at'] != null && $params['publish_at'] != '') ? Carbon::parse($params['publish_at'])->format('Y-m-d H:i:s') : date('Y-m-d H:i:s');
        $params['is_activated'] = false;

        $article = Article::create([
            'title'           => $params['title'],
            'slug'            => Helper::slug($params['title']),
            'description'     => $params['content'],
            'editor'          => 'gutenberg',
            'important'       => 5,
            'publish_at'      => $publishAt,
            'created_by'      => auth('api')->user()->id,
            'preview'         => md5(rand(0, 1000) . date('Y-m-dH:i:s')),
            'type'            => 'question',
            'question_status' => 0,
            'is_published'    => 0,
            'is_activated'    => 0,
            'created_at'      => date('Y-m-d H:i:s'),
            'updated_at'      => date('Y-m-d H:i:s')
        ]);

        if (isset($params['category']) && $params['category'] != null) {
            CategoryDetail::insert(['article_id' => $article->id, 'category_id' => $params['category'], 'created_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s')]);
        }

        if (isset($params['subCategory']) && $params['subCategory'] != null) {
            CategoryDetail::insert(['article_id' => $article->id, 'category_id' => $params['subCategory'], 'created_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s')]);
        }

        if (isset($params['keyword']) && is_array($params['keyword'])) {
            KeywordDetail::insert([
                'keyword_id' => $params['keyword'],
                'ref_id'     => $article->id,
                'type'       => 'article',
                'created_at' => date('Y-m-d H:i:s'),
                'updated_at' => date('Y-m-d H:i:s'),
            ]);
        }

        Notify::create([
            'content' => "[" . auth('api')->user()->name . "] just posted a question.",
            'module' => 'question',
            'item_id' => $article->id
        ]);
        event(new NotifyEvent());

        return response()->json(['data' => ['status' => 'success']], 200);
    }
}
