<?php

namespace Dashboard\Controllers\Support;

use Dashboard\Core\Controller;
use Dashboard\Core\Jobs\JobDispatcher;
use Dashboard\Jobs\SendDiscordWebhook;
use Dashboard\Services\AvatarService;
use PDO;

class TicketController extends Controller
{
    public function __construct()
    {
        abort_perm(['MANAGE_SUPPORT', 'MANAGE_SUPPORT_TICKETS']);
    }

    public function index()
    {
        if (isset($_GET["page"])) {
            if (!is_numeric($_GET["page"])) {
                $_GET["page"] = 1;
            }
            $page = intval(get("page"));
        } else {
            $page = 1;
        }
	    
				if (auth()->user()->supportPermissions('STRICT_MANAGE_SUPPORT_TICKETS')) {
					$categories = db()->query("SELECT * FROM SupportCategories");
					$categories = $categories->fetchAll();
				} else {
					$authorizedCategories = auth()->user()->supportPermissions('VIEW_CATEGORY');
					$categories = db()->prepare("SELECT * FROM SupportCategories WHERE id IN (" . implode(",", array_fill(0, count($authorizedCategories), "?")) . ")");
					$categories->execute($authorizedCategories);
					$categories = $categories->fetchAll(PDO::FETCH_ASSOC);
				}
				$categoryIDs = array_column($categories, "id");

        $visiblePageCount = 5;
        $limit = 50;

        if (isset($_GET["search"])) {
	        $tickets = db()->prepare("SELECT count(S.id) FROM Supports S INNER JOIN SupportCategories SC ON S.categoryID = SC.id INNER JOIN Accounts A ON S.accountID = A.id WHERE S.categoryID IN (" . implode(",", $categoryIDs) . ") AND (S.title LIKE :search OR SC.name LIKE :search) ORDER BY S.id DESC");
	        $tickets->execute(array(
		        "search" => '%' . get("search") . '%'
	        ));
	        $itemsCount = $tickets->fetchColumn();
	        $pageCount = ceil($itemsCount / $limit);
	        if ($page > $pageCount) {
		        $page = 1;
	        }
	        $visibleItemsCount = $page * $limit - $limit;
	        
	        $tickets = db()->prepare("SELECT S.*, SC.name as categoryName, A.username, A.realname FROM Supports S INNER JOIN SupportCategories SC ON S.categoryID = SC.id INNER JOIN Accounts A ON S.accountID = A.id WHERE S.categoryID IN (" . implode(",", $categoryIDs) . ") AND (S.title LIKE :search OR SC.name LIKE :search) ORDER BY S.id DESC LIMIT $visibleItemsCount, $limit");
	        $tickets->execute(array(
		        "search" => '%' . get("search") . '%'
	        ));
        } else if (isset($_GET["category"]) && isset($_GET["status"])) {
	        if (!in_array(get("category"), $categoryIDs))
		        abort_403();
	        
	        if (get("status") == "waiting") {
		        $questionMarks = "?, ?";
		        $binds = array(get("category"), 1, 3);
	        }
	        if (get("status") == "answered") {
		        $questionMarks = "?";
		        $binds = array(get("category"), 2);
	        }
	        if (get("status") == "closed") {
		        $questionMarks = "?";
		        $binds = array(get("category"), 4);
	        }
	        
	        $tickets = db()->prepare("SELECT count(S.id) FROM Supports S INNER JOIN SupportCategories SC ON S.categoryID = SC.id INNER JOIN Accounts A ON S.accountID = A.id WHERE S.categoryID = ? AND S.statusID IN ($questionMarks) ORDER BY S.id DESC");
	        $tickets->execute($binds);
	        $itemsCount = $tickets->fetchColumn();
	        $pageCount = ceil($itemsCount / $limit);
	        if ($page > $pageCount) {
		        $page = 1;
	        }
	        $visibleItemsCount = $page * $limit - $limit;
	        
	        $tickets = db()->prepare("SELECT S.*, SC.name as categoryName, A.username, A.realname FROM Supports S INNER JOIN SupportCategories SC ON S.categoryID = SC.id INNER JOIN Accounts A ON S.accountID = A.id WHERE S.categoryID = ? AND S.statusID IN ($questionMarks) ORDER BY S.id DESC LIMIT $visibleItemsCount, $limit");
	        $tickets->execute($binds);
        } else if (isset($_GET["category"])) {
					if (!in_array(get("category"), $categoryIDs))
						abort_403();
					
	        $tickets = db()->prepare("SELECT count(S.id) FROM Supports S INNER JOIN SupportCategories SC ON S.categoryID = SC.id INNER JOIN Accounts A ON S.accountID = A.id WHERE S.categoryID = ? ORDER BY S.id DESC");
	        $tickets->execute(array(get("category")));
	        $itemsCount = $tickets->fetchColumn();
	        $pageCount = ceil($itemsCount / $limit);
	        if ($page > $pageCount) {
		        $page = 1;
	        }
	        $visibleItemsCount = $page * $limit - $limit;
					
					$tickets = db()->prepare("SELECT S.*, SC.name as categoryName, A.username, A.realname FROM Supports S INNER JOIN SupportCategories SC ON S.categoryID = SC.id INNER JOIN Accounts A ON S.accountID = A.id WHERE S.categoryID = ? ORDER BY S.id DESC LIMIT $visibleItemsCount, $limit");
	        $tickets->execute(array(get("category")));
        } else if (isset($_GET["status"])) {
					if (get("status") == "waiting") {
						$questionMarks = "?, ?";
						$binds = array(1, 3);
					}
	        if (get("status") == "answered") {
		        $questionMarks = "?";
		        $binds = array(2);
	        }
	        if (get("status") == "closed") {
		        $questionMarks = "?";
		        $binds = array(4);
	        }
					
	        $tickets = db()->prepare("SELECT count(S.id) FROM Supports S INNER JOIN SupportCategories SC ON S.categoryID = SC.id INNER JOIN Accounts A ON S.accountID = A.id WHERE S.statusID IN ($questionMarks) AND S.categoryID IN (". implode(",", $categoryIDs) .") ORDER BY S.id DESC");
	        $tickets->execute($binds);
	        $itemsCount = $tickets->fetchColumn();
	        $pageCount = ceil($itemsCount / $limit);
	        if ($page > $pageCount) {
		        $page = 1;
	        }
	        $visibleItemsCount = $page * $limit - $limit;
	        
	        $tickets = db()->prepare("SELECT S.*, SC.name as categoryName, A.username, A.realname FROM Supports S INNER JOIN SupportCategories SC ON S.categoryID = SC.id INNER JOIN Accounts A ON S.accountID = A.id WHERE S.statusID IN ($questionMarks) AND S.categoryID IN (". implode(",", $categoryIDs) .") ORDER BY S.id DESC LIMIT $visibleItemsCount, $limit");
	        $tickets->execute($binds);
        } else {
	        if (count($categoryIDs) > 0) {
		        $tickets = db()->query("SELECT count(S.id) FROM Supports S INNER JOIN SupportCategories SC ON S.categoryID = SC.id INNER JOIN Accounts A ON S.accountID = A.id WHERE S.categoryID IN (". implode(",", $categoryIDs) .") ORDER BY S.id DESC");
		        $itemsCount = $tickets->fetchColumn();
		        $pageCount = ceil($itemsCount / $limit);
		        if ($page > $pageCount) {
			        $page = 1;
		        }
		        $visibleItemsCount = $page * $limit - $limit;
		        $tickets = db()->query("SELECT S.*, SC.name as categoryName, A.username, A.realname FROM Supports S INNER JOIN SupportCategories SC ON S.categoryID = SC.id INNER JOIN Accounts A ON S.accountID = A.id WHERE S.categoryID IN (". implode(",", $categoryIDs) .") ORDER BY S.id DESC LIMIT $visibleItemsCount, $limit");
	        } else {
		        $tickets = null;
		        $itemsCount = 0;
		        $pageCount = ceil($itemsCount / $limit);
		        if ($page > $pageCount) {
			        $page = 1;
		        }
	        }
        }
        $tickets = $tickets ? $tickets->fetchAll() : [];

        return view('support.tickets.index', compact('tickets', 'categories', 'page', 'visiblePageCount', 'pageCount'));
    }

    public function show($id)
    {
        $supportAnswers = null;
        $supportMessages = null;
        $supportFieldValues = null;

        $support = db()->prepare("SELECT S.*, A.username, A.realname, SC.name as categoryName FROM Supports S INNER JOIN Accounts A ON S.accountID = A.id INNER JOIN SupportCategories SC ON S.categoryID = SC.id WHERE S.id = ?");
        $support->execute(array($id));
        $support = $support->fetch();

        if (!$support) return view('404');
				
				if (!auth()->user()->canManageSupportCategory('VIEW_CATEGORY', $support["categoryID"]))
					abort_403();

        $supportMessages = db()->prepare("SELECT SM.* FROM SupportMessages SM WHERE SM.supportID = ? ORDER BY SM.creationDate ASC");
        $supportMessages->execute(array($id));
        $supportMessages = array_map(function ($supportMessage) use ($support) {
						if ($supportMessage["accountID"] == '0') {
							$supportMessage["realname"] = moduleSettings('ai', 'name');
							$supportMessage["username"] = moduleSettings('ai', 'name');
							$supportMessage["avatar"] = '/assets/core/images/avatars/ai.png';
						} else {
							$account = db()->prepare("SELECT username, realname FROM Accounts WHERE id = ?");
							$account->execute(array($supportMessage["accountID"]));
							$account = $account->fetch();
							if ($account) {
								$supportMessage["realname"] = $account["realname"];
								$supportMessage["username"] = $account["username"];
								$supportMessage["avatar"] = AvatarService::get($supportMessage["accountID"], $supportMessage["realname"]);
							} else {
								$supportMessage["realname"] = "Unknown";
								$supportMessage["username"] = "Unknown";
								$supportMessage["avatar"] = AvatarService::DEFAULT_AVATAR;
							}
						}
					
            if ($supportMessage["writeLocation"] == 1) {
              $supportMessage["message"] = markdown()->convertToHtml($supportMessage["message"]);
            }
            else {
	            $message = $supportMessage["message"];
              $search = array("%username%", "%message%", "%servername%", "%serverip%", "%serverversion%");
	            if ($supportMessage["accountID"] == '0') {
		            $message = markdown()->convertToHtml($message);
	            }
              $replace = array($support["realname"], $message, settings('serverName'), settings('serverIP'), settings('serverVersion'));
              $template = moduleSettings('support', 'messageTemplate');
              $supportMessage["message"] = str_replace($search, $replace, $template);
            }
						
            return $supportMessage;
        }, $supportMessages->fetchAll());

        $supportAnswers = db()->query("SELECT * FROM SupportAnswers");
        $supportAnswers = $supportAnswers->fetchAll();

        $supportFieldValues = db()->prepare("SELECT CSFV.value, CSV.field FROM CustomSupportFieldValues CSFV INNER JOIN CustomSupportFields CSV ON CSV.id = CSFV.fieldID WHERE CSFV.supportID = ?");
        $supportFieldValues->execute(array($id));
        $supportFieldValues = $supportFieldValues->fetchAll();

        return view('support.tickets.show', compact('support', 'supportMessages', 'supportAnswers', 'supportFieldValues'));
    }

    public function close($id)
    {
		    $support = db()->prepare("SELECT S.*, A.username, A.realname, SC.name as categoryName FROM Supports S INNER JOIN Accounts A ON S.accountID = A.id INNER JOIN SupportCategories SC ON S.categoryID = SC.id WHERE S.id = ?");
		    $support->execute(array($id));
		    $support = $support->fetch();
		    
		    if (!$support) return view('404');
	    
		    if (!auth()->user()->canManageSupportCategory('CLOSE_TICKETS', $support["categoryID"]))
			    abort_403();
				
        $closeSupport = db()->prepare("UPDATE Supports SET statusID = ?, updateDate = ? WHERE id = ?");
        $closeSupport->execute(array(4, datetime(), $id));
				
		    JobDispatcher::dispatch((new SendDiscordWebhook('support.ticket.closed', [
			    "username" => auth()->user()->displayName(),
			    "category" => $support["categoryName"],
			    "title" => $support["title"],
			    "message" => strip_tags(input('message')),
			    "dashboard_url" => websiteUrl("/dashboard/support/tickets/$id")
		    ])));
				
        return back();
    }

    public function destroy($id)
    {
				$support = db()->prepare("SELECT * FROM Supports WHERE id = ?");
				$support->execute(array($id));
				$support = $support->fetch();
				
				if (!$support) return view('404');
				
		    if (!auth()->user()->canManageSupportCategory('DELETE_TICKETS', $support["categoryID"]))
			    abort_403();
				
        $deleteSupport = db()->prepare("DELETE FROM Supports WHERE id = ?");
        $deleteSupport->execute(array($id));
        $deleteSupportMessages = db()->prepare("DELETE FROM SupportMessages WHERE supportID = ?");
        $deleteSupportMessages->execute(array($id));
        redirect(url('dashboard.support.tickets.index'));
    }

    public function destroySelected()
    {
        $data = file_get_contents('php://input');
        $data = json_decode($data, true);

        foreach ($data["selectedItems"] as $supportID) {
		        $support = db()->prepare("SELECT * FROM Supports WHERE id = ?");
		        $support->execute(array($supportID));
		        $support = $support->fetch();
		        
		        if (!$support) continue;
		        
		        if (!auth()->user()->canManageSupportCategory('DELETE_TICKETS', $support["categoryID"]))
			        continue;
						
            $deleteSupport = db()->prepare("DELETE FROM Supports WHERE id = ?");
            $deleteSupport->execute(array($supportID));
            $deleteSupportMessages = db()->prepare("DELETE FROM SupportMessages WHERE supportID = ?");
            $deleteSupportMessages->execute(array($supportID));
        }
        response()->json([
          'status' => 'success',
        ]);
    }

}