<?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 Illuminate\Support\Str;
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)
			->where('publish_at', '<=', now());
		
		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)
			->where('publish_at', '<=', now())
			->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)
			->where('publish_at', '<=', now())
			->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)
			->where('publish_at', '<=', now())
			->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)
			->where('publish_at', '<=', now())
			->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)
			->where('publish_at', '<=', now())
			->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)
			->where('publish_at', '<=', now())
			->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)
			->where('publish_at', '<=', now())
			->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(['author', 'articleCategoryDetails', 'keyword_detail'])
			->select('*')
			->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)->where('publish_at', '<=', now());
		}
		
		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);
	}

	/**
	 * Show preview from cache (no database query)
	 * GET /api/article/preview-temp/{key}
	 */
	public function showPreviewTemp(Request $request, $key)
	{
		// Validate key format (UUID)
		if (!Str::isUuid($key)) {
			return response()->json(['error' => 'Invalid preview key'], 400);
		}

		// Get data from cache
		$previewData = Cache::get('preview_temp_' . $key);

		if (!$previewData) {
			return response()->json(['error' => 'Preview expired or not found'], 404);
		}

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