<?php

namespace App\Http\Controllers\Admin;

use App\ArticleCategory;
use App\ArticleCategoryDetail;
use App\Events\SaveDataEvent;
use App\Gutenberg;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Keyword;
use App\KeywordDetail;
use App\Laravue\Acl;
use App\Seo;
use App\SeoFormat;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use App\Article;
use App\Http\Resources\Admin\ArticleResource;
use Illuminate\Support\Facades\Artisan;
use Validator;
use Auth;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;

/**
 * Class ColumnController
 *
 * @package App\Http\Controllers
 */
class ColumnController extends Controller
{
	const ITEM_PER_PAGE = 20;
	const POST_TYPE = 'column';
	protected $_pathFile;
	protected $_pathTemp;

	public function __construct()
	{
		$this->_pathFile = public_path('uploads/image/article/');
		$this->_pathTemp = storage_path('app/public/uploads/temp/image/');
	}

	public function index(Request $request)
	{
		$searchParams = $request->all();
		$user = auth('api')->user();

		$limit = Arr::get($searchParams, 'limit', static::ITEM_PER_PAGE);
		$keyword = Arr::get($searchParams, 'keyword', '');
		$status = Arr::get($searchParams, 'status', '');
		$list = Article::with(['articleCategoryDetails.articleCategory', 'author'])->notDeleted()->where('type', static::POST_TYPE);

		if (!$user->hasRole(['admin', 'manager']) && !$user->can(Acl::PERMISSION_ARTICLE_MANAGE)) {
			$list->where('user_id', $user->id);
		}
		if (!$user->hasRole(['admin', 'manager']) && !$user->can(Acl::PERMISSION_ARTICLE_ONLY_MANAGE)) {
			$list->where('id', 0);
		}
		if (!empty($keyword)) {
			$list->where(function ($query) use ($keyword) {
				$query->where('title', 'LIKE', '%' . $keyword . '%')
					->orWhereHas('articleCategoryDetails.articleCategory', function ($q) use ($keyword) {
						$q->where('name', 'LIKE', '%' . $keyword . '%');
					})
					->orWhereHas('author', function ($q) use ($keyword) {
						$q->where('name', 'LIKE', '%' . $keyword . '%');
					});
			});
		}
		if ($status != '') {
			$list->where('is_activated', $status);
		}
		$list->orderBy('id', 'DESC');

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

	public function all()
	{
		$list = Article::select('id', 'title', 'slug')->notDeleted()->where('type', static::POST_TYPE)->orderBy('id');

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

	public function show($id = 0)
	{
		$article = Article::with(['articleCategoryDetails.articleCategory', 'keyword_detail.keyword', 'author'])
			->notDeleted()
			->where('id', $id)
			->where('type', static::POST_TYPE)
			->first();
		if (!isset($article)) return response()->json(['errors' => 'Article is not valid'], 403);

		return new ArticleResource($article);
	}

	public function store(Request $request)
	{
		$validator = Validator::make($request->all(), ['title' => ['required'], 'is_activated' => ['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');
		$content = $params['content'];
		if ($params['editor'] == 'gutenberg') {
			if ($params['content'] != '' && $params['content'] != null && ($params['gu_content'] == '' || $params['gu_content'] == null)) {
				$params['gu_content'] = $params['content'];
			}
			$content = $this->gutenbergRenderContent($params['gu_content']);
		} else {
			$params['editor'] = 'tinymce';
			$params['gu_content'] = null;
		}

		$content = str_replace("../../../../uploads/image", "/uploads/image", $content);
		$content = str_replace("../../../uploads/image", "/uploads/image", $content);
		$content = str_replace("../../uploads/image", "/uploads/image", $content);
		$content = str_replace("../uploads/image", "/uploads/image", $content);
		$content = str_replace("uploads/image", "/uploads/image", $content);
		$content = str_replace("//uploads/image", "/uploads/image", $content);
		$content = str_replace("///uploads/image", "/uploads/image", $content);
		$content = str_replace('<h2></h2>', '<p>&nbsp;</p>', $content);
		$content = str_replace('<h2>&nbsp;</h2>', '<p>&nbsp;</p>', $content);
		$content = str_replace('<h2>&nbsp;&nbsp;</h2>', '<p>&nbsp;</p>', $content);
		$content = str_replace('<h2>&nbsp;&nbsp;&nbsp;</h2>', '<p>&nbsp;</p>', $content);
		$content = str_replace('<h2>&nbsp;&nbsp;&nbsp;&nbsp;</h2>', '<p>&nbsp;</p>', $content);
		$content = str_replace('href="../', 'href="/', $content);
		$content = str_replace('href="fortune-teller/', 'href="/fortune-teller/', $content);

		$slug = Helper::slug($params['slug']);
		if (empty($slug)) $slug = Helper::slug($params['title']);

		$previewCode = null;
		if ($params['is_activated'] != true && $params['is_activated'] != "true" && $params['is_activated'] != 1) $previewCode = md5(rand(0, 1000) . date('Y-m-dH:i:s'));

		$author = $params['user_id'];
		if ($author == null || $author == 0 || $author == "") $author = auth('api')->user()->id;

		$article = Article::create([
			'title'             => $params['title'],
			'slug'              => $slug,
			'description'       => $params['description'],
			'editor'            => $params['editor'],
			'gu_content'        => $params['gu_content'],
			'content'           => $content,
			'thumbnail'         => $params['thumbnail'],
			'shop_id'           => $params['shop_id'],
			'fortune_teller_id' => $params['fortune_teller_id'],
			'important'         => $params['important'],
			'publish_at'        => $publishAt,
			'created_by'        => auth('api')->user()->id,
			'user_id'           => $author,
			'preview'           => $previewCode,
			'type'              => static::POST_TYPE,
			'is_published'      => ($params['is_activated'] === true && $publishAt <= date('Y-m-d H:i:s')) ? 1 : 0,
			'is_activated'      => ($params['is_activated'] === true) ? 1 : 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) {
			$insertCategory = [];
			foreach ($params['category'] as $item) {
				if ($item == "" || $item == null) continue;
				$insertCategory[] = ['article_id' => $article->id, 'article_category_id' => $item, 'created_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s')];
			}
			if (count($insertCategory) > 0) ArticleCategoryDetail::insert($insertCategory);
		}

		$keywordsStr = "";
		if (isset($params['keyword']) && is_array($params['keyword'])) {
			$keywords = [];
			foreach ($params['keyword'] as $item) {
				$tag = trim($item['text']);
				$checkKeyword = Keyword::where('is_deleted', 0)
					->where(function ($query) use ($tag) {
						$query->where('name', $tag)
							->orWhere('name', strtolower($tag))
							->orWhere('name', strtoupper($tag))
							->orWhere('name', ucfirst($tag));
					})->first();
				if (!isset($checkKeyword) || $checkKeyword->id == null) {
					$checkKeyword = Keyword::create([
						'name'         => $tag,
						'is_activated' => true,
						'is_deleted'   => false,
						'created_at'   => date('Y-m-d H:i:s'),
						'updated_at'   => date('Y-m-d H:i:s'),
					]);
				}
				$keywords[] = [
					'keyword_id' => $checkKeyword->id,
					'ref_id'     => $article->id,
					'type'       => 'article',
					'created_at' => date('Y-m-d H:i:s'),
					'updated_at' => date('Y-m-d H:i:s'),
				];

				$keywordsStr .= $tag . ', ';
			}
			if (count($keywords) > 0) KeywordDetail::insert($keywords);
		}

		$this->updateSeoInfo($article->id, $params['title'], $slug, $keywordsStr, $params['description'], $params['thumbnail'] ?? '');
		Artisan::call('cache:clear');

		return new ArticleResource($article);
	}

	public function update($id = 0, Request $request)
	{
		$validator = Validator::make($request->all(), ['title' => ['required'], 'is_activated' => ['required']]);
		if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
		$article = Article::notDeleted()->where('id', $id)->first();
		if (!isset($article)) return response()->json(['errors' => 'Article is not valid'], 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');

		$content = $params['content'];
		if ($params['editor'] == 'gutenberg') {
			if ($params['content'] != '' && $params['content'] != null && ($params['gu_content'] == '' || $params['gu_content'] == null)) {
				$params['gu_content'] = $params['content'];
			}
			$content = $this->gutenbergRenderContent($params['gu_content']);
		} else {
			$params['editor'] = 'tinymce';
			$params['gu_content'] = null;
		}

		$content = str_replace("../../../../uploads/image", "/uploads/image", $content);
		$content = str_replace("../../../uploads/image", "/uploads/image", $content);
		$content = str_replace("../../uploads/image", "/uploads/image", $content);
		$content = str_replace("../uploads/image", "/uploads/image", $content);
		$content = str_replace("uploads/image", "/uploads/image", $content);
		$content = str_replace("//uploads/image", "/uploads/image", $content);
		$content = str_replace("///uploads/image", "/uploads/image", $content);
		$content = str_replace('<h2></h2>', '<p>&nbsp;</p>', $content);
		$content = str_replace('<h2>&nbsp;</h2>', '<p>&nbsp;</p>', $content);
		$content = str_replace('<h2>&nbsp;&nbsp;</h2>', '<p>&nbsp;</p>', $content);
		$content = str_replace('<h2>&nbsp;&nbsp;&nbsp;</h2>', '<p>&nbsp;</p>', $content);
		$content = str_replace('<h2>&nbsp;&nbsp;&nbsp;&nbsp;</h2>', '<p>&nbsp;</p>', $content);
		$content = str_replace('href="../', 'href="/', $content);
		$content = str_replace('href="fortune-teller/', 'href="/fortune-teller/', $content);

		$slug = Helper::slug($params['slug']);
		if (empty($slug)) $slug = Helper::slug($params['title']);

		$previewCode = $article->preview;
		if ($params['is_activated'] != true && $params['is_activated'] != "true" && $params['is_activated'] != 1) {
			if ($previewCode == null || $previewCode == "") $previewCode = md5(rand(0, 1000) . date('Y-m-dH:i:s'));
		}

		$author = $params['user_id'];
		if ($author == null || $author == 0 || $author == "") $author = auth('api')->user()->id;

		$article->update([
			'title'             => $params['title'],
			'slug'              => $slug,
			'description'       => $params['description'],
			'editor'            => $params['editor'],
			'gu_content'        => $params['gu_content'],
			'content'           => $content,
			'thumbnail'         => $params['thumbnail'],
			'shop_id'           => $params['shop_id'],
			'fortune_teller_id' => $params['fortune_teller_id'],
			'important'         => $params['important'],
			'publish_at'        => $publishAt,
			'preview'           => $previewCode,
			'type'              => static::POST_TYPE,
			'user_id'           => $author,
			'is_published'      => ($params['is_activated'] === true && $publishAt <= date('Y-m-d H:i:s')) ? 1 : 0,
			'is_activated'      => ($params['is_activated'] === true) ? 1 : 0,
			'updated_at'        => date('Y-m-d H:i:s')
		]);
		if ($article->user_id == null || $article->user_id == '') $article->update(['user_id' => auth('api')->user()->id]);

		ArticleCategoryDetail::where('article_id', $article->id)->delete();
		if (isset($params['category']) && $params['category'] != null) {
			$insertCategory = [];
			foreach ($params['category'] as $item) {
				if ($item == "" || $item == null) continue;
				$cateCheck = ArticleCategory::where('is_activated', true)->where('is_deleted', false)->where('id', $item)->count();
				if ($cateCheck > 0) $insertCategory[] = ['article_id' => $article->id, 'article_category_id' => $item, 'created_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s')];
			}
			if (count($insertCategory) > 0) ArticleCategoryDetail::insert($insertCategory);
		}

		$keywordsStr = "";
		if (isset($params['keyword']) && is_array($params['keyword'])) {
			KeywordDetail::where('ref_id', $article->id)->where('type', 'article')->delete();
			$keywords = [];
			foreach ($params['keyword'] as $item) {
				$tag = trim($item['text']);
				$checkKeyword = Keyword::where('is_deleted', 0)
					->where(function ($query) use ($tag) {
						$query->where('name', $tag)
							->orWhere('name', strtolower($tag))
							->orWhere('name', strtoupper($tag))
							->orWhere('name', ucfirst($tag));
					})->first();
				if (!isset($checkKeyword) || $checkKeyword->id == null) {
					$checkKeyword = Keyword::create([
						'name'         => $tag,
						'is_activated' => true,
						'is_deleted'   => false,
						'created_at'   => date('Y-m-d H:i:s'),
						'updated_at'   => date('Y-m-d H:i:s'),
					]);
				}

				$keywords[] = [
					'keyword_id' => $checkKeyword->id,
					'ref_id'     => $article->id,
					'type'       => 'article',
					'created_at' => date('Y-m-d H:i:s'),
					'updated_at' => date('Y-m-d H:i:s'),
				];

				$keywordsStr .= $tag . ', ';
			}
			if (count($keywords) > 0) KeywordDetail::insert($keywords);
		}

		$this->updateSeoInfo($article->id, $params['title'], $slug, $keywordsStr, $params['description'], $params['thumbnail'] ?? '');
		Artisan::call('cache:clear');

		return response()->json(null, 204);
	}

	public function destroy($id = 0)
	{
		$article = Article::notDeleted()->where('id', $id)->where('type', static::POST_TYPE)->first();
		if (!isset($article)) response()->json(['error' => 'Ehhh! Can not delete this article'], 403);

		try {
			$article->update(['is_deleted' => true]);
			Seo::where('uri', 'like', "/column/detail/" . $article->id . "/%")->delete();
			event(new SaveDataEvent());
			Artisan::call('cache:clear');
		} catch (\Exception $ex) {
			response()->json(['error' => $ex->getMessage()], 403);
		}

		return response()->json(null, 204);
	}

	public function destroyMultiple(Request $request)
	{
		$validator = Validator::make($request->all(), ['ids' => 'required']);
		if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
		$listIds = $request->get('ids', []);
		$articleList = Article::notDeleted()->whereIn('id', $listIds)->where('type', static::POST_TYPE)->get();

		if ($articleList->count() <= 0) response()->json(['error' => 'Article is not valid.'], 403);
		try {
			Article::notDeleted()->whereIn('id', $listIds)->where('type', static::POST_TYPE)->update(['is_deleted' => true]);
			foreach ($listIds as $pId) {
				Seo::where('uri', 'like', "/column/detail/" . $pId . "/%")->delete();
			}
			event(new SaveDataEvent());
			Artisan::call('cache:clear');
		} catch (\Exception $ex) {
			response()->json(['error' => $ex->getMessage()], 403);
		}

		return response()->json(null, 204);
	}

	public function activateMultiple(Request $request)
	{
		$validator = Validator::make($request->all(), ['ids' => 'required']);
		if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
		$listIds = $request->get('ids', []);
		$articleList = Article::notDeleted()->whereIn('id', $listIds)->where('type', static::POST_TYPE)->get();

		if ($articleList->count() <= 0) response()->json(['error' => 'Article is not valid.'], 403);
		try {
			Article::notDeleted()->whereIn('id', $listIds)->where('type', static::POST_TYPE)->update(['is_activated' => true]);
			event(new SaveDataEvent());
		} catch (\Exception $ex) {
			response()->json(['error' => $ex->getMessage()], 403);
		}

		return response()->json(null, 204);
	}

	public function deactivateMultiple(Request $request)
	{
		$validator = Validator::make($request->all(), ['ids' => 'required']);
		if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
		$listIds = $request->get('ids', []);
		$articleList = Article::notDeleted()->whereIn('id', $listIds)->where('type', static::POST_TYPE)->get();

		if ($articleList->count() <= 0) response()->json(['error' => 'Article is not valid.'], 403);
		try {
			Article::notDeleted()->whereIn('id', $listIds)->where('type', static::POST_TYPE)->update(['is_activated' => false]);
			event(new SaveDataEvent());
		} catch (\Exception $ex) {
			response()->json(['error' => $ex->getMessage()], 403);
		}

		return response()->json(null, 204);
	}

	public function uploadImage(Request $request)
	{
		if ($request->hasFile('image')) {
			$file = $request->file('image');
			$baseName = $file->getClientOriginalName();
			$fileName = md5($baseName . rand(1111, 9999) . date('YmdHis')) . '.' . $file->getClientOriginalExtension();
			$file->move($this->_pathTemp, $fileName);
			chmod($this->_pathTemp . $fileName, 0777);
			return response()->json(['status' => 'success', 'message' => 'Upload Success.', 'file_name' => $fileName, 'baseName' => $baseName], 200);
		}

		return response()->json(['status' => 'error', 'message' => 'Upload Fail.', 'file_name' => null], 403);
	}

	public function uploadImages(Request $request)
	{
		if ($request->hasFile('file')) {
			$file = $request->file('file');
			$baseName = $file->getClientOriginalName();
			$fileName = md5($baseName . rand(1111, 9999) . date('YmdHis')) . '.' . $file->getClientOriginalExtension();
			$file->move($this->_pathFile, $fileName);
			chmod($this->_pathFile . $fileName, 0777);
			return response()->json(['hasSuccess' => true, 'message' => 'Upload Success.', 'file_name' => $fileName, 'baseName' => $baseName, 'files' => ['file' => $fileName]], 200);
		}

		return response()->json(['hasSuccess' => false, 'message' => 'Upload Fail.', 'file_name' => null, 'files' => null], 403);
	}

	private function updateSeoInfo($postId, $postTitle, $slug, $keywords, $postContent, $image = '')
	{
		Seo::where('uri', 'like', "/column/detail/" . $postId . "/%")->delete();
		Seo::create([
			'uri'         => '/column/detail/' . $postId . '/' . $slug,
			'title'       => $postTitle . " | コラム | " . config('settings.site_name'),
			'keywords'    => $keywords,
			'description' => $postContent,
			'image'       => $image,
			'type'        => 'column',
			'post_id'     => $postId,
			'created_at'  => date('Y-m-d H:i:s'),
			'updated_at'  => date('Y-m-d H:i:s'),
		]);
	}

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

		return $renderContent;
	}

	/**
	 * Store column data temporarily in cache for preview (without saving to database)
	 * POST /api/admin/column/preview-temp
	 */
	public function previewTemp(Request $request)
	{
		$validator = Validator::make($request->all(), ['title' => ['required']]);
		if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);

		$params = $request->all();
		$content = $params['content'] ?? '';

		// Process Gutenberg content if needed
		if (($params['editor'] ?? 'tinymce') == 'gutenberg') {
			if ($content != '' && $content != null && (($params['gu_content'] ?? '') == '')) {
				$params['gu_content'] = $content;
			}
			$content = $this->gutenbergRenderContent($params['gu_content'] ?? '');
		}

		// Clean paths (reuse logic from store)
		$content = str_replace("../../../../uploads/image", "/uploads/image", $content);
		$content = str_replace("../../../uploads/image", "/uploads/image", $content);
		$content = str_replace("../../uploads/image", "/uploads/image", $content);
		$content = str_replace("../uploads/image", "/uploads/image", $content);
		$content = str_replace("uploads/image", "/uploads/image", $content);
		$content = str_replace("//uploads/image", "/uploads/image", $content);
		$content = str_replace("///uploads/image", "/uploads/image", $content);

		// Generate UUID key
		$previewKey = Str::uuid()->toString();

		// Prepare preview data
		$previewData = [
			'title' => $params['title'],
			'slug' => Helper::slug($params['slug'] ?? $params['title']),
			'description' => $params['description'] ?? '',
			'content' => $content,
			'thumbnail' => $params['thumbnail'] ?? '',
			'publish_at' => $params['publish_at'] ?? now(),
			'type' => static::POST_TYPE,
			'author' => auth('api')->user(),
			'created_at' => now(),
		];

		// Store in cache for 30 minutes
		Cache::put('preview_temp_' . $previewKey, $previewData, now()->addMinutes(30));

		// Generate preview URL
		$previewUrl = url('/column/preview-temp/' . $previewKey);

		return response()->json([
			'preview_key' => $previewKey,
			'preview_url' => $previewUrl,
		], 200);
	}
}
