<?php

namespace Main\Controllers\Suggestion;

use Exception;
use Main\Core\Controller;
use Main\Services\AvatarService;
use Main\Services\CkEditorImageUploadService;
use Main\Services\SeoService;
use Main\Services\UserService;
use PDO;

class SuggestionController extends Controller
{
		protected string $route_type = 'suggestions';
	
    public function index()
    {
	      SeoService::set('suggestions.index');
				
        if (get("page")) {
            if (!is_numeric(get("page"))) {
                $_GET["page"] = 1;
            }
            $page = intval(get("page"));
        } else {
            $page = 1;
        }

        $suggestionLimit = 20;

        $itemsCount = db()->query("SELECT count(id) from Suggestions");
        $itemsCount = $itemsCount->fetchColumn();

        $pageCount = ceil($itemsCount / $suggestionLimit);
        if ($page > $pageCount) {
            $page = 1;
        }
        $visibleItemsCount = $page * $suggestionLimit - $suggestionLimit;
        $visiblePageCount = 5;
        
				switch (get("sort")) {
					case "recent-activity":
						$sort = "S.updatedDate";
						break;
					case "likes":
						$sort = "S.likesCount";
						break;
					default:
						$sort = "S.creationDate";
						break;
				}
				
        $suggestions = db()->query("SELECT S.*, A.username, A.realname FROM Suggestions S INNER JOIN Accounts A ON A.id = S.accountID ORDER BY $sort DESC LIMIT $visibleItemsCount, $suggestionLimit");
        $suggestions = array_map(function ($suggestion) {
					$suggestion["user"] = [
						'id' => $suggestion["accountID"],
						'username' => $suggestion["username"],
						'displayName' => $suggestion["realname"],
						'avatar' => AvatarService::get($suggestion["accountID"], $suggestion["realname"]),
					];
					
					return $suggestion;
        }, $suggestions->fetchAll(PDO::FETCH_ASSOC));
				
        $categories = db()->query("SELECT * FROM SuggestionCategories");
        $categories = $categories->fetchAll(PDO::FETCH_ASSOC);

        return $this->view('suggestions.index', compact('suggestions', 'categories', 'page', 'pageCount', 'visiblePageCount'));
    }

    public function show($id, $slug)
    {
        $suggestion = db()->prepare("SELECT S.*, A.username, A.realname FROM Suggestions S INNER JOIN Accounts A ON A.id = S.accountID WHERE S.id = ?");
        $suggestion->execute(array($id));
        $suggestion = $suggestion->fetch();

        if (!$suggestion) abort_404();
	    
	      SeoService::set('suggestions.show', [
					'suggestion_title' => $suggestion["title"],
	      ]);
				
				$suggestion["user"] = [
					'id' => $suggestion["accountID"],
					'username' => $suggestion["username"],
					'displayName' => $suggestion["realname"],
					'avatar' => AvatarService::get($suggestion["accountID"], $suggestion["realname"]),
					'roles' => UserService::getRoles($suggestion["accountID"]),
				];
	      $suggestion["user"]["primaryRole"] = $suggestion["user"]["roles"][0];
				$suggestion["likes"] = $suggestion["likesCount"];
				$suggestion["dislikes"] = $suggestion["dislikesCount"];
	    
		    $replies = db()->prepare("SELECT SC.*, A.username, A.realname FROM SuggestionReplies SC INNER JOIN Accounts A ON A.id = SC.accountID WHERE SC.suggestionID = ?");
		    $replies->execute(array($suggestion["id"]));
	      $suggestion["replies"] = array_map(function ($reply) {
		      $reply["message"] = markdown()->convertToHtml($reply["message"]);
					$reply["canEdit"] = auth()->check() && ($reply["accountID"] == auth()->user()->id() || auth()->user()->can('MANAGE_SUGGESTIONS'));
					
					$reply["user"] = [
						'id' => $reply["accountID"],
						'username' => $reply["username"],
						'displayName' => $reply["realname"],
						'avatar' => AvatarService::get($reply["accountID"], $reply["realname"]),
						'roles' => UserService::getRoles($reply["accountID"]),
					];
					$reply["user"]["primaryRole"] = $reply["user"]["roles"][0];
					
		      return $reply;
	      }, $replies->fetchAll(PDO::FETCH_ASSOC));
		    
		    if (!cookies()->has('suggestionID')) {
			    $updateSuggestionViews = db()->prepare("UPDATE Suggestions SET views = views + 1 WHERE id = ?");
			    $updateSuggestionViews->execute(array($suggestion["id"]));
			    setcookie("suggestionID", $suggestion["id"]);
		    }
				
        $category = db()->prepare("SELECT * FROM SuggestionCategories WHERE id = ?");
        $category->execute(array($suggestion["categoryID"]));
        $suggestion["category"] = $category->fetch();
				
				$suggestion["isLiked"] = false;
				$suggestion["isDisliked"] = false;
        if (auth()->check()) {
	        $isLikedQuery = db()->prepare("SELECT * FROM SuggestionLikes WHERE suggestionID = ? AND accountID = ?");
	        $isLikedQuery->execute(array($suggestion["id"], auth()->user()->id()));
	        $isLikedQuery = $isLikedQuery->fetch();
	        
	        if ($isLikedQuery) {
		        $suggestion["isLiked"] = true;
	        } else {
		        $isDislikedQuery = db()->prepare("SELECT * FROM SuggestionDislikes WHERE suggestionID = ? AND accountID = ?");
		        $isDislikedQuery->execute(array($suggestion["id"], auth()->user()->id()));
		        $isDislikedQuery = $isDislikedQuery->fetch();
		        if ($isDislikedQuery) {
			        $suggestion["isDisliked"] = true;
		        }
	        }
        }
				
				$suggestion["content"] = markdown()->convertToHtml($suggestion["content"]);
	    
		    $suggestion["canEdit"] = auth()->check() && ($suggestion["accountID"] == auth()->user()->id() || auth()->user()->can('MANAGE_SUGGESTIONS'));

        return $this->view('suggestions.show', compact('suggestion'));
    }

    public function create()
    {
	      SeoService::set('suggestions.create');
				
        $categories = db()->query("SELECT * FROM SuggestionCategories");
        $categories = $categories->fetchAll(PDO::FETCH_ASSOC);

        return $this->view('suggestions.create', compact('categories'));
    }

    public function store()
    {
        validate([
            "categoryID" => "required",
            "title" => "required",
            "message" => "required"
        ]);
	    
		    if (recaptcha()->isEnabled('post_suggestion') && !recaptcha()->verify()) {
			    return back()->flash('error', t__('Spam detected!'));
		    }
				
				$category = db()->prepare("SELECT * FROM SuggestionCategories WHERE id = ?");
				$category->execute(array(input("categoryID")));
				$category = $category->fetch();
				if (!$category) abort_404();
	   
				$title = sanitize(input("title"));
		    $slug = slugify(input("title"));

        $insertSuggestion = db()->prepare("INSERT INTO Suggestions (title, slug, content, categoryID, accountID, views, likesCount, dislikesCount, creationDate, updatedDate) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
        $insertSuggestion->execute(array($title, $slug, input("message"), $category["id"], auth()->user()->id(), 0, 0, 0, datetime(), datetime()));
        $suggestionID = db()->lastInsertId();

        redirect(url("suggestions.show", ["id" => $suggestionID, "slug" => slugify(input("title"))]));
    }

    public function edit($id)
    {
        if (!auth()->user()->can('MANAGE_SUGGESTIONS')) {
            $suggestion = db()->prepare("SELECT * FROM Suggestions WHERE id = ? AND accountID = ?");
            $suggestion->execute(array($id, auth()->user()->id()));
            $suggestion = $suggestion->fetch();
        } else {
            $suggestion = db()->prepare("SELECT * FROM Suggestions WHERE id = ?");
            $suggestion->execute(array($id));
            $suggestion = $suggestion->fetch();
        }

        if (!$suggestion) abort_404();
	    
	      SeoService::set('suggestions.edit', [
					'suggestion_title' => $suggestion["title"],
	      ]);

        $categories = db()->query("SELECT * FROM SuggestionCategories");
        $categories = $categories->fetchAll(PDO::FETCH_ASSOC);

        return $this->view('suggestions.edit', compact('suggestion', 'categories'));
    }

    public function update($id)
    {
        if (!auth()->user()->can('MANAGE_SUGGESTIONS')) {
            $suggestion = db()->prepare("SELECT * FROM Suggestions WHERE id = ? AND accountID = ?");
            $suggestion->execute(array($id, auth()->user()->id()));
            $suggestion = $suggestion->fetch();
        } else {
            $suggestion = db()->prepare("SELECT * FROM Suggestions WHERE id = ?");
            $suggestion->execute(array($id));
            $suggestion = $suggestion->fetch();
        }

        if (!$suggestion) abort_404();

        validate([
            "categoryID" => "required",
            "title" => "required",
            "message" => "required"
        ]);
	    
	      $title = sanitize(input("title"));
		    if (input("title") != $suggestion["title"]) {
			    $slug = slugify(input("title"));
		    } else {
			    $slug = $suggestion["slug"];
		    }
				
        $updateSuggestion = db()->prepare("UPDATE Suggestions SET title = ?, slug = ?, content = ?, categoryID = ?, updatedDate = ? WHERE id = ?");
        $updateSuggestion->execute(array($title, $slug, input("message"), input("categoryID"), datetime(), $suggestion["id"]));

        redirect(url("suggestions.show", ["id" => $suggestion["id"], "slug" => $slug]));
    }

    public function destroy($id)
    {
        if (!auth()->user()->can('MANAGE_SUGGESTIONS')) {
            $deleteSuggestion = db()->prepare("DELETE FROM Suggestions WHERE id = ? AND accountID = ?");
            $deleteSuggestion->execute(array($id, auth()->user()->id()));
        } else {
            $deleteSuggestion = db()->prepare("DELETE FROM Suggestions WHERE id = ?");
            $deleteSuggestion->execute(array($id));
        }

        redirect(url("suggestions.index"));
    }

    public function reaction($id)
    {
        $suggestion = db()->prepare("SELECT * FROM Suggestions WHERE id = ?");
        $suggestion->execute(array($id));
        $suggestion = $suggestion->fetch();

        if (!$suggestion) abort_404();

        validate([
            'reaction' => 'required|in:upvote,downvote',
        ]);

        if (input("reaction") == "upvote") {
		        $isDislikedQuery = db()->prepare("SELECT * FROM SuggestionDislikes WHERE suggestionID = ? AND accountID = ?");
		        $isDislikedQuery->execute(array($suggestion["id"], auth()->user()->id()));
		        $isDislikedQuery = $isDislikedQuery->fetch();
						
		        if ($isDislikedQuery) {
			        $deleteSuggestionDislikes = db()->prepare("DELETE FROM SuggestionDislikes WHERE suggestionID = ? AND accountID = ?");
			        $deleteSuggestionDislikes->execute(array($suggestion["id"], auth()->user()->id()));
			        $updateSuggestion = db()->prepare("UPDATE Suggestions SET dislikesCount = dislikesCount - 1 WHERE id = ?");
			        $updateSuggestion->execute(array($suggestion["id"]));
		        }
			       
		        $insertSuggestionLikes = db()->prepare("INSERT INTO SuggestionLikes (suggestionID, accountID) VALUES (?, ?)");
		        $status = $insertSuggestionLikes->execute(array($suggestion["id"], auth()->user()->id()));
		        if ($status) {
			        $updateSuggestion = db()->prepare("UPDATE Suggestions SET likesCount = likesCount + 1 WHERE id = ?");
			        $updateSuggestion->execute(array($suggestion["id"]));
		        }
        } else {
		        $isLikedQuery = db()->prepare("SELECT * FROM SuggestionLikes WHERE suggestionID = ? AND accountID = ?");
		        $isLikedQuery->execute(array($suggestion["id"], auth()->user()->id()));
		        $isLikedQuery = $isLikedQuery->fetch();
						
		        if ($isLikedQuery) {
			        $deleteSuggestionLikes = db()->prepare("DELETE FROM SuggestionLikes WHERE suggestionID = ? AND accountID = ?");
			        $deleteSuggestionLikes->execute(array($suggestion["id"], auth()->user()->id()));
			        $updateSuggestion = db()->prepare("UPDATE Suggestions SET likesCount = likesCount - 1 WHERE id = ?");
			        $updateSuggestion->execute(array($suggestion["id"]));
		        }
	        
		        $insertSuggestionDislikes = db()->prepare("INSERT INTO SuggestionDislikes (suggestionID, accountID) VALUES (?, ?)");
		        $status = $insertSuggestionDislikes->execute(array($suggestion["id"], auth()->user()->id()));
		        if ($status) {
			        $updateSuggestion = db()->prepare("UPDATE Suggestions SET dislikesCount = dislikesCount + 1 WHERE id = ?");
			        $updateSuggestion->execute(array($suggestion["id"]));
		        }
        }
				
				return back();
    }
	
	public function reply($id)
	{
		validate([
			"message" => "required"
		]);
		
		if (recaptcha()->isEnabled('reply_suggestion') && !recaptcha()->verify()) {
			return back()->flash('error', t__('Spam detected!'));
		}
		
		$suggestion = db()->prepare("SELECT * FROM Suggestions WHERE id = ?");
		$suggestion->execute(array($id));
		$suggestion = $suggestion->fetch();
		
		if (!$suggestion) abort_404();
		
		$insertReply = db()->prepare("INSERT INTO SuggestionReplies (message, accountID, suggestionID, creationDate, updatedDate) VALUES (?, ?, ?, ?, ?)");
		$insertReply->execute(array(input("message"), auth()->user()->id(), $suggestion["id"], datetime(), datetime()));
		
		$updateSuggestion = db()->prepare("UPDATE Suggestions SET updatedDate = ? WHERE id = ?");
		$updateSuggestion->execute(array(datetime(), $suggestion["id"]));
		
		return back()->flash('success', t__('Your reply has been successfully sent.'));
	}
	
	public function upload()
	{
		try {
			$image = CkEditorImageUploadService::upload($_FILES["upload"], "/apps/main/public/images/suggestions/uploads/");
			response()->json([
				'url' => '/assets/core/images/suggestions/uploads/' . $image,
			]);
		} catch (Exception $e) {
			response()->json([
				'status' => false,
				'error'  => $e->getMessage(),
			]);
		}
	}
}