<?php

namespace App\Http\Controllers\Admin;

use App\Article;
use App\Http\Controllers\Controller;
use App\Http\Resources\Admin\LinkHistoryResource;
use App\LinkHistory;
use App\LinkHistoryDetail;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use App\Link;
use App\Http\Resources\Admin\LinkResource;
use Validator;

/**
 * Class LinkController
 *
 * @package App\Http\Controllers
 */
class LinkController extends Controller
{
    const ITEM_PER_PAGE = 20;
    private $_csvPath;

    public function __construct()
    {
        $this->_csvPath = storage_path('app/public/uploads/temp/csv/');
    }

    public function index(Request $request)
    {
        $searchParams = $request->all();
        $list = Link::notDeleted();
        $limit = Arr::get($searchParams, 'limit', static::ITEM_PER_PAGE);
        $keyword = Arr::get($searchParams, 'keyword', '');
        $status = Arr::get($searchParams, 'status', '');

        if ($status != '') {
            $list->where('is_activated', $status);
        }
        if (!empty($keyword)) {
            $list->where('name', 'LIKE', "%$keyword%")
                ->orderByRaw("CASE WHEN name = '". $keyword ."' THEN 0
                                  WHEN name LIKE '". $keyword ."%' THEN 1
                                  WHEN name LIKE '%". $keyword ."%' THEN 2
                                  ELSE 3
                             END, word_length DESC");
        }
        $list->orderBy('word_length', 'ASC');

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

    public function all()
    {
        $list = Link::select('id', 'name', 'content')
            ->notDeleted()
            ->where('is_activated', true)
            ->orderBy('word_length', 'ASC');

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

    public function show($id = 0)
    {
        $link = Link::notDeleted()->where('id', $id)->first();
        if (!isset($link)) return response()->json(['errors' => 'Link is not valid'], 403);
        return new LinkResource($link);
    }

    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), ['name' => ['required'], 'content' => ['required'], 'is_activated' => ['required']]);
        if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
        $params = $request->all();

        $checkLink = Link::where('name', $params['name'])->where('is_activated', true)->where('is_deleted', false)->first();
        if (isset($checkLink) && $checkLink->id != null) return response()->json(['data' => ['status' => 'error', 'message' => 'Link already exists.']], 200);
        $type = filter_var($params['content'], FILTER_VALIDATE_URL) ? 1 : 0;

        $link = Link::create([
            'name'         => $params['name'],
            'description'  => $params['description'],
            'content'      => $params['content'],
            'type'         => $type,
            'word_length'  => strlen($params['name']),
            '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')
        ]);

        return new LinkResource($link);
    }

    public function update($id = 0, Request $request)
    {
        $validator = Validator::make($request->all(), ['name' => ['required'], 'content' => ['required'], 'is_activated' => ['required']]);
        if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
        $link = Link::notDeleted()->where('id', $id)->first();
        if (!isset($link)) return response()->json(['errors' => 'Link is not valid'], 403);

        $params = $request->all();
        $checkLink = Link::where('name', $params['name'])->where('is_activated', true)->where('is_deleted', false)->where('id', '!=', $link->id)->first();
        if (isset($checkLink) && $checkLink->id != null) return response()->json(['data' => ['status' => 'error', 'message' => 'Link already exists.']], 200);
        $type = filter_var($params['content'], FILTER_VALIDATE_URL) ? 1 : 0;

        $link->update([
            'name'         => $params['name'],
            'description'  => $params['description'],
            'content'      => $params['content'],
            'type'         => $type,
            'word_length'  => strlen($params['name']),
            'is_activated' => ($params['is_activated'] === true) ? 1 : 0,
            'updated_at'   => date('Y-m-d H:i:s'),
        ]);

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

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

        try {
            $link->update(['is_deleted' => true]);
        } 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', []);
        $links = Link::notDeleted()->whereIn('id', $listIds)->get();
        if ($links->count() <= 0) response()->json(['error' => 'Link is not valid.'], 403);
        try {
            Link::notDeleted()->whereIn('id', $listIds)->update(['is_deleted' => true]);
        } 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', []);
        $links = Link::notDeleted()->whereIn('id', $listIds)->get();
        if ($links->count() <= 0) response()->json(['error' => 'Link is not valid.'], 403);
        try {
            Link::notDeleted()->whereIn('id', $listIds)->update(['is_activated' => true]);
        } 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', []);
        $links = Link::notDeleted()->whereIn('id', $listIds)->get();
        if ($links->count() <= 0) response()->json(['error' => 'Link is not valid.'], 403);
        try {
            Link::notDeleted()->whereIn('id', $listIds)->update(['is_activated' => false]);
        } catch (\Exception $ex) {
            response()->json(['error' => $ex->getMessage()], 403);
        }

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

    public function replaceInit()
    {
        $articles = Article::select('id', 'title', 'content')->where('is_deleted', false)->get();
        $history = LinkHistory::create([
            'key'        => md5(date('YmdHis') . rand(0, 10000)),
            'total'      => $articles->count(),
            'created_at' => date('Y-m-d H:i:s'),
            'updated_at' => date('Y-m-d H:i:s')
        ]);

        foreach ($articles as $article) {
            LinkHistoryDetail::create([
                'link_history_id' => $history->id,
                'article_id'      => $article->id,
                'title'           => $article->title,
                'content'         => $article->content,
                'total'           => 0,
                'status'          => 0,
                'created_at'      => date('Y-m-d H:i:s'),
                'updated_at'      => date('Y-m-d H:i:s')
            ]);
        }

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

    public function replaceInitSelected(Request $request)
    {
        $ids = $request->get('ids');
        if (!is_array($ids) || count($ids) <= 0) return response()->json(['key' => null], 200);

        $articles = Article::select('id', 'title', 'content')
            ->where('is_deleted', false)
            ->whereIn('id', $ids)
            ->get();
        $history = LinkHistory::create([
            'key'        => md5(date('YmdHis') . rand(0, 10000)),
            'total'      => $articles->count(),
            'created_at' => date('Y-m-d H:i:s'),
            'updated_at' => date('Y-m-d H:i:s')
        ]);

        foreach ($articles as $article) {
            LinkHistoryDetail::create([
                'link_history_id' => $history->id,
                'article_id'      => $article->id,
                'title'           => $article->title,
                'content'         => $article->content,
                'total'           => 0,
                'status'          => 0,
                'created_at'      => date('Y-m-d H:i:s'),
                'updated_at'      => date('Y-m-d H:i:s')
            ]);
        }

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

    public function replaceItem(Request $request, $id = 0)
    {
        $params = $request->all();
        $key = Arr::get($params, 'key', '');

        if ($key == '' || $key == null || $id == '' || $id == 0) return response()->json(['error' => 'Ehhh! Can not replace this post'], 403);

        $history = LinkHistory::select('id')->where('key', $key)->first();
        if (!isset($history)) return response()->json(['error' => 'Ehhh! Can not replace this post'], 403);

        $historyDetail = LinkHistoryDetail::where('link_history_id', $history->id)->where('article_id', $id)->first();
        if (!isset($historyDetail)) return response()->json(['error' => 'Ehhh! Can not replace this post'], 403);

        $article = Article::select('content')->where('is_deleted', false)->where('id', $id)->first();
        if (!isset($article)) return response()->json(['error' => 'This article is not found.'], 403);

        $links = Link::select('id', 'name', 'content', 'type')
            ->where('is_deleted', false)
            ->where('is_activated', true)
            ->orderBy('word_length', 'DESC')
            ->get();

        if ($links->count() > 0) {
            try {
                $articleContent = $article->content;
                foreach ($links as $item) {
                    $keyword = trim($item->name);
                    $link = trim($item->content);
                    if ($keyword == "" || $link == "") continue;
                    $articleContent = $this->replacePostContent($articleContent, $keyword, $link, $item->type);
                }
                Article::where('id', $id)->update(['content' => $articleContent, 'updated_at' => date('Y-m-d H:i:s')]);
                $historyDetail->update(['status' => 1]);
            } catch (\Exception $exception) {
                logger("Error: Replace");
                $historyDetail->update(['status' => 2]);
            }
        }

        return response()->json(['status' => 'success', 'id' => $historyDetail->id, 'message' => ''], 200);
    }

    public function replaceContent(Request $request) {
        try {
            $status = 'error';
            $content = '';
            if ($request->has('type') && $request->get('type') != "" && $request->get('type') != null
                && $request->has('content') && $request->get('content') != null && $request->get('content') != "") {
                $type = $request->get('type');
                $content = $request->get('content');

                $links = Link::select('id', 'name', 'content', 'type')
                    ->where('is_deleted', false)
                    ->where('is_activated', true)
                    ->orderBy('word_length', 'DESC')
                    ->get();

                if ($links->count() > 0) {
                    try {
                        foreach ($links as $item) {
                            $keyword = trim($item->name);
                            $link = trim($item->content);
                            if ($keyword == "" || $link == "") continue;
                            $content = $this->replacePostContent($content, $keyword, $link, $item->type);
                            //if ($type == 'gutenberg')
                        }
                    } catch (\Exception $exception) {
                        logger("Error: Replace content");
                    }
                }

                $status = 'success';
            }

            return response()->json(['data' => ['status' => $status, 'content' => $content]], 200);
        } catch (\Exception $exception) {
            logger("Error: Replace content");
            return response()->json(['data' => ['status' => 'error', 'content' => ""]], 200);
        }
    }

    public function history(Request $request)
    {
        $searchParams = $request->all();
        $list = LinkHistory::select('*');
        $limit = Arr::get($searchParams, 'limit', static::ITEM_PER_PAGE);
        $keyword = Arr::get($searchParams, 'keyword', '');

        if (!empty($keyword)) {
            $list->where('key', 'LIKE', '%' . $keyword . '%');
        }
        $list->orderBy('id', 'DESC');

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

    public function csvUpload(Request $request) {
        if (!$request->hasFile('csv')) return response()->json(['status' => 'error', 'fileName' => null, 'baseName' => null, 'message' => 'CSV not found.'], 200);

        $file = $request->file('csv');
        $baseName = $file->getClientOriginalName();
        $fileNameKey = md5($baseName . rand(1111, 9999) . date('YmdHis'));
        $fileName = $fileNameKey . '.' . $file->getClientOriginalExtension();
        $file->move($this->_csvPath, $fileName);
        $csvFilePath = $this->_csvPath . $fileName;
        $total = 0;
        $checkColumn = false;
        $isHeader = true;
        $headerCol = "";

        try {
            chmod($csvFilePath, 0777);
            $fileContent = fopen($csvFilePath, "r");
            while (!feof($fileContent)) {
                $row = fgetcsv($fileContent);
                if (isset($row) && is_array($row) && count($row) >= 2) {
                    if ($isHeader) {
                        if (!$checkColumn) {
                            foreach ($row as $it) {
                                if (trim($it) == "Keyword" || trim($it) == "keyword" || trim($it) == "Keyword") {
                                    $headerCol .= "Keyword";
                                }
                                if (trim($it) == "URL" || trim($it) == "Url" || trim($it) == "url" || trim($it) == "URL") {
                                    $headerCol .= "URL";
                                }
                            }
                            if ($headerCol == "KeywordURL" || $headerCol == "URLKeyword") $checkColumn = true;
                        }
                        $isHeader = false;
                    } else {
                        $total++;
                    }
                }
            }
            fclose($fileContent);
            if (!$checkColumn || $total <= 0) return response()->json(['status' => 'error', 'fileName' => null, 'baseName' => null, 'message' => 'CSV is invalid.'], 200);
        } catch (\Exception $exception) {
            logger($exception->getMessage());
        }

        return response()->json(['status' => 'success', 'fileName' => $fileName, 'baseName' => $baseName, 'total' => $total], 200);
    }

    public function csvImport(Request $request) {
        $validator = Validator::make($request->all(), ['file' => ['required']]);
        if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
        $params = $request->all();
        $fileName = Arr::get($params, 'file', '');
        $overwrite = Arr::get($params, 'overwrite', false);
        $csvFilePath = $this->_csvPath . $fileName;
        $isHeader = true;
        $keywordIdx = null;
        $urlIdx = null;
        $total = 0;
        $insertList = [];

        try {
            $fileContent = fopen($csvFilePath, "r");
            while (!feof($fileContent)) {
                $row = fgetcsv($fileContent);
                if (isset($row) && is_array($row) && count($row) >= 2) {
                    if ($isHeader) {
                        foreach ($row as $k => $it) {
                            if (trim($it) == "Keyword" || trim($it) == "keyword" || trim($it) == "Keyword") $keywordIdx = $k;
                            if (trim($it) == "URL" || trim($it) == "Url" || trim($it) == "url" || trim($it) == "URL") $urlIdx = $k;
                        }
                        $isHeader = false;
                    } else {
                        $keywordText = isset($row[$keywordIdx]) ? $row[$keywordIdx] : '';
                        $urlText = isset($row[$urlIdx]) ? $row[$urlIdx] : '';
                        $keywordText = trim($keywordText);
                        $urlText = trim($urlText);

                        $checkItem = Link::where('is_deleted', false)->where('name', $keywordText)->count();
                        if ($checkItem <= 0) {
                            $insertList[] = [
                                'name'         => $keywordText,
                                'content'      => $urlText,
                                'type'         => filter_var($urlText, FILTER_VALIDATE_URL) ? 1 : 0,
                                'word_length'  => strlen($keywordText),
                                'is_activated' => 1,
                                'created_at'   => date('Y-m-d H:i:s'),
                                'updated_at'   => date('Y-m-d H:i:s')
                            ];
                            $total++;
                        } else {
                            if ($overwrite) {
                                Link::where('is_deleted', false)->where('name', $keywordText)->update([
                                    'content'      => $urlText,
                                    'type'         => filter_var($urlText, FILTER_VALIDATE_URL) ? 1 : 0,
                                    'word_length'  => strlen($keywordText),
                                    'is_activated' => 1,
                                    'updated_at'   => date('Y-m-d H:i:s')
                                ]);
                                $total++;
                            }
                        }

                    }
                }
            }
            fclose($fileContent);
            if (count($insertList) > 0) Link::insert($insertList);
            return response()->json(['status' => 'success', 'total' => $total, 'message' => ''], 200);
        } catch (\Exception $exception) {
            logger($exception->getMessage());
            return response()->json(['status' => 'error', 'total' => $total, 'message' => 'Data is not valid.'], 200);
        }
    }

    private function replacePostContent($content, $keyword, $link, $type = 0) {
        if ($content != "" && $keyword != "" && $link != "") {
            try {
                $subst = $link;
                $re = "/(<a.*?>.*?<\/a>|<h1.*?>.*?<\/h1>|<h2.*?>.*?<\/h2>|<h3.*?>.*?<\/h3>|<h4.*?>.*?<\/h4>|<h5.*?>.*?<\/h5>|<h6.*?>.*?<\/h6>|<figure.*?>.*?<\/figure>|https:\/\/.*?\/|http:\/\/.*?\/|<!--.*?-->|id=\".*?\"|style=\".*?\"|class=\".*?\")(*SKIP)(*FAIL)|" . $keyword . "/";
                if ($type == 1) $subst = '<a href="' . $link . '">' . $keyword . '</a>';
                $content = preg_replace($re, $subst, $content);
            } catch (\Exception $exception) {
                logger("Error Replace Keyword: " . $keyword);
            }
        }
        return $content;
    }

    private function replacePostContentGutenberg($content, $keyword, $link, $type = 0) {
        //h1->h6
        //p
        //li
        //th
        //td

        if ($content != "" && $keyword != "" && $link != "") {
            try {
                $subst = $link;
                $re = "/(<a.*?>.*?<\/a>|<h1.*?>.*?<\/h1>|<h2.*?>.*?<\/h2>|<h3.*?>.*?<\/h3>|<h4.*?>.*?<\/h4>|<h5.*?>.*?<\/h5>|<h6.*?>.*?<\/h6>|<figure.*?>.*?<\/figure>|https:\/\/.*?\/|http:\/\/.*?\/|<!--.*?-->|id=\".*?\"|style=\".*?\"|class=\".*?\")(*SKIP)(*FAIL)|" . $keyword . "/";
                if ($type == 1) $subst = '<a href="' . $link . '">' . $keyword . '</a>';
                $content = preg_replace($re, $subst, $content);
            } catch (\Exception $exception) {
                logger("Error Replace Keyword: " . $keyword);
            }
        }
        return $content;
    }
}
