<?php
    /**
     * Comment Class
     *
     * @package Wojo Framework
     * @author wojoscripts.com
     * @copyright 2023
     * @version 5.50: Comment.php, v1.00 8/2/2023 11:36 AM Gewa Exp $
     *
     */
    if (!defined('_WOJO')) {
        die('Direct access to this location is not allowed.');
    }
    
    class Comment
    {
        const mTable = 'comments';
        
        public int $auto_approve;
        public bool $rating;
        public int $timesince;
        public string $blacklist_words;
        public int $char_limit;
        public string $dateformat;
        public bool $notify_new;
        public int $perpage;
        public bool $public_access;
        public bool $show_captcha;
        public string $sorting;
        public bool $name_req;
        
        /**
         * index
         *
         * @return void
         */
        public function index(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->META_M_COMMENTS;
            $tpl->caption = Language::$word->META_M_COMMENTS;
            $tpl->subtitle = Language::$word->MU_INFO;
            
            
            $counter = Database::Go()->count(self::mTable)->where('active', 1, '<')->run();
            $pager = Paginator::instance();
            $pager->items_total = $counter;
            $pager->default_ipp = App::Core()->perpage;
            $pager->path = Url::url(Router::$path, '?');
            $pager->paginate();
            
            $sql = "
            SELECT c.id, c.user_id, c.parent_id, c.product_id, c.body, c.created, c.username as uname, u.username, CONCAT(u.fname, ' ', u.lname) as name
              FROM `" . self::mTable . '` as c
              LEFT JOIN `' . User::mTable . '` as u ON u.id = c.user_id
              WHERE c.active = ?
              ORDER BY c.created
              DESC ' . $pager->limit;
            
            $tpl->data = Database::Go()->rawQuery($sql, array(0))->run();
            $tpl->pager = $pager;
            
            $tpl->template = 'admin/comment';
        }
        
        /**
         * settings
         *
         * @return void
         */
        public function settings(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->META_M_CONFIGURE;
            $tpl->caption = Language::$word->META_M_CONFIGURE;
            $tpl->subtitle = Language::$word->CMT_INFO;
            
            $tpl->row = self::configuration();
            $tpl->template = 'admin/comment';
        }
        
        /**
         * processConfig
         *
         * @return void
         */
        public function processConfig(): void
        {
            $validate = Validator::run($_POST);
            $validate
                ->set('auto_approve', Language::$word->CMT_AUTOA)->required()->numeric()
                ->set('rating', Language::$word->CMT_RATING)->required()->numeric()
                ->set('char_limit', Language::$word->CMT_CHARS)->required()->numeric()
                ->set('notify_new', Language::$word->CMT_NOTIFY)->required()->numeric()
                ->set('timesince', Language::$word->CMT_SINCE)->required()->numeric()
                ->set('perpage', Language::$word->CMT_CPP)->required()->numeric()
                ->set('public_access', Language::$word->CMT_PUBLIC)->required()->numeric()
                ->set('show_captcha', Language::$word->CMT_SHOWCAP)->required()->numeric()
                ->set('sorting', Language::$word->CMT_SORTING)->required()->string()
                ->set('dateformat', Language::$word->CMT_DATEFORMAT)->required()->string()
                ->set('name_req', Language::$word->CMT_NAMEREQ)->required()->numeric()
                ->set('blacklist_words', Language::$word->CMT_BLACK)->required()->string(true, true);
            
            $safe = $validate->safe();
            
            if (count(Message::$msgs) === 0) {
                $data = array(
                    'comments' => array(
                        'auto_approve' => $safe->auto_approve,
                        'rating' => $safe->rating,
                        'char_limit' => $safe->char_limit,
                        'notify_new' => $safe->notify_new,
                        'perpage' => $safe->perpage,
                        'public_access' => $safe->public_access,
                        'show_captcha' => $safe->show_captcha,
                        'sorting' => $safe->sorting,
                        'dateformat' => $safe->dateformat,
                        'timesince' => $safe->timesince,
                        'name_req' => $safe->name_req,
                        'blacklist_words' => $safe->blacklist_words,
                    )
                );
                
                Message::msgReply(File::writeToFile(ADMINBASE . '/snippets/comments.json', json_encode($data, JSON_PRETTY_PRINT)), 'success', Language::$word->CMT_UPDATE_OK);
                Logger::writeLog(Language::$word->CMT_UPDATE_OK);
            } else {
                Message::msgSingleStatus();
            }
        }
        
        /**
         * processComment
         *
         * @return void
         * @throws \PHPMailer\PHPMailer\Exception
         */
        public function processComment(): void
        {
            
            $validate = Validator::run($_POST);
            $config = self::configuration();
            
            $validate
                ->set('id', 'ID')->required()->numeric()
                ->set('username', Language::$word->NAME)->string()->required()
                ->set('message', Language::$word->MESSAGE)->required()->string(true, true)
                ->set('parent_id', 'PARENT')->required()->numeric()
                ->set('product_id', 'PRODUCT')->required()->numeric()
                ->set('url', 'URL')->required()->path()
                ->set('type', Language::$word->CMT_PUBLIC)->string();
            
            if ($config->show_captcha) {
                if ($_POST['action'] != 'reply') {
                    if (Session::get('wcaptcha') != $_POST['captcha']) {
                        Message::$msgs['captcha'] = Language::$word->CAPTCHA;
                    }
                }
            }
            $safe = $validate->safe();
            
            if (count(Message::$msgs) === 0) {
                $data = array(
                    'parent_id' => ($safe->parent_id == -1) ? 0 : $safe->parent_id,
                    'user_id' => (App::Auth()->logged_in) ? App::Auth()->uid : 0,
                    'product_id' => $safe->product_id,
                    'username' => (App::Auth()->logged_in) ? App::Auth()->name : $safe->username,
                    'rating' => (isset($_POST['rating'])) ? intval($_POST['rating']) : 0,
                    'body' => Validator::censored($safe->message, $config->blacklist_words),
                    'www' => Url::getIP(),
                    'active' => ($config->auto_approve) ? 1 : 0,
                );
                
                $last_id = Database::Go()->insert(self::mTable, $data)->run();
                
                // Set product ratings
                if ($safe->parent_id == -1) {
                    Database::Go()->rawQuery('UPDATE `' . Product::mTable . '` SET `ratings` = `ratings` + 1, `likes` = `likes` + ' . $data['rating'] . ' WHERE `id` = ?', array($safe->product_id))->run();
                }
                
                if ($config->auto_approve) {
                    $message = Language::$word->CMT_MSGOK1;
                    $tpl = App::View(PLUGINBASE . '/comments/');
                    $tpl->template = '_loadComment.tpl.php';
                    $tpl->data = $this->singleComment($last_id);
                    $tpl->conf = $config;
                    
                    $json['counter'] = intval($_POST['counter']);
                    $json['html'] = $tpl->render();
                } else {
                    $message = Language::$word->CMT_MSGOK2;
                }
                
                $json['type'] = 'success';
                $json['title'] = Language::$word->SUCCESS;
                $json['message'] = $message;
                print json_encode($json);

                if ($config->notify_new) {
                    $core = App::Core();
                    $user = (App::Auth()->logged_in) ? App::Auth()->name : $safe->username;
                    $mailer = Mailer::sendMail();
                    $tpl = Database::Go()->select(Content::eTable, array('body', 'subject'))->where('typeid', 'newComment', '=')->first()->run();
                    $body = str_replace(array(
                        '[LOGO]',
                        '[CEMAIL]',
                        '[DATE]',
                        '[COMPANY]',
                        '[SITE_NAME]',
                        '[NAME]',
                        '[MESSAGE]',
                        '[PAGEURL]',
                        '[IP]',
                        '[FB]',
                        '[TW]',
                        '[SITEURL]'
                    ), array(
                        $core->plogo,
                        $core->site_email,
                        date('Y'),
                        $core->company,
                        $core->site_name,
                        $user,
                        $data['body'],
                        SITEURL . $safe->url,
                        Url::getIP(),
                        $core->social->facebook,
                        $core->social->twitter,
                        SITEURL
                    ), $tpl->body);
                    
                    $mailer->setFrom($core->site_email, $core->company);
                    $mailer->addAddress($core->site_email, $core->company);
                    
                    $mailer->isHTML();
                    $mailer->Subject = $tpl->subject;
                    $mailer->Body = $body;
                    $mailer->send();
                }
                
            } else {
                Message::msgSingleStatus();
            }
        }
        
        /**
         * commentTree
         *
         * @param int $id
         * @return array
         */
        public function commentTree(int $id): array
        {
            $counter = Database::Go()->count(self::mTable, "WHERE parent_id = 0 AND product_id = $id AND active = 1")->run();
            
            $config = self::configuration();
            
            $pager = Paginator::instance();
            $pager->items_total = $counter;
            $pager->default_ipp = $config->perpage;
            $pager->path = Url::url(Router::$path, '?');
            $pager->paginate();
            
            if (isset($_GET['order']) and count(explode('|', $_GET['order'])) == 2) {
                list($sort, $order) = explode('|', $_GET['order']);
                $sort = Validator::sanitize($sort, 'default', 16);
                $order = Validator::sanitize($order, 'default', 4);
                if (in_array($sort, array(
                    'vote_up',
                    'vote_down',
                    'created'
                ))) {
                    $ord = ($order == 'DESC') ? ' DESC' : ' ASC';
                    $sorting = $sort . $ord;
                } else {
                    $sorting = ' created ' . $config->sorting;
                }
            } else {
                $sorting = ' created ' . $config->sorting;
            }
            
            $sql = "
            SELECT c.id, c.user_id, c.product_id, c.parent_id, c.vote_down, c.vote_up, c.body, c.created, c.rating, c.username as uname, u.username, CONCAT(u.fname, ' ', u.lname) AS name, u.avatar
              FROM `" . self::mTable . '` AS c
                INNER JOIN (SELECT id FROM `' . self::mTable . "`
                WHERE product_id = ?
                AND parent_id = 0
                AND active = 1
                ORDER BY $sorting " . $pager->limit . ') AS ch ON ch.id IN (c.id, c.parent_id)
              LEFT JOIN `' . User::mTable . "` AS u ON u.id = c.user_id
              WHERE product_id = ?
              AND c.active = 1
              ORDER BY $sorting";
            
            $data = Database::Go()->rawQuery($sql, array($id, $id))->run();
            
            $comments = array();
            $result = array();
            
            foreach ($data as $row) {
                $comments['id'] = $row->id;
                $comments['user_id'] = $row->user_id;
                $comments['product_id'] = $row->product_id;
                $comments['vote_up'] = $row->vote_up;
                $comments['vote_down'] = $row->vote_down;
                $comments['rating'] = $row->rating;
                $comments['parent_id'] = $row->parent_id;
                $comments['body'] = $row->body;
                $comments['created'] = $row->created;
                $comments['name'] = $row->name;
                $comments['username'] = $row->username;
                $comments['uname'] = $row->uname;
                $comments['avatar'] = $row->avatar;
                $result[$row->id] = $comments;
            }
            return $result;
        }
        
        /**
         * getCommentList
         *
         * @param array|null $array
         * @param int $parent_id
         * @param string $class
         * @return string
         */
        public function getCommentList(array|null $array, int $parent_id = 0, string $class = 'threaded'): string
        {
            $config = self::configuration();
            $submenu = false;
            $class = ($parent_id == 0) ? "wojo comments $class" : 'comments';
            $delete = (App::Auth()->is_Admin()) ? '<a class="delete"><i class="icon trash"></i></a>' : null;
            $html = '';
            
            foreach ($array as $key => $row) {
                if ($row['parent_id'] == $parent_id) {
                    if ($submenu === false) {
                        $submenu = true;
                        $html .= "<div class=\"$class\">\n";
                    }
                    if ($row['uname']) {
                        $user = '<span class="author">' . $row['uname'] . '</span>';
                        $avatar = '<div class="avatar"><img src="' . UPLOADURL . '/avatars/blank.svg" alt=""></div>';
                    } else {
                        $user = $row['name'];
                        $avatar = '<a class="avatar"><img src="' . UPLOADURL . '/avatars/' . ($row['avatar'] ? : 'blank.svg') . '" alt=""></a>';
                    }
                    
                    $html .= '<div class="comment" data-id="' . $row['id'] . '" id="comment_' . $row['id'] . '">';
                    $html .= $avatar;
                    $html .= '<div class="content">';
                    $html .= $user;
                    $html .= '<div class="metadata">';
                    $html .= '<span class="date">' . Date::doDate($config->dateformat, $row['created']) . '</span>';
                    
                    if ($parent_id == 0) {
                        $html .= '<div class="wojo stars">';
                        for ($x = 1; $x <= $row['rating']; $x++) {
                            $html .= '<span class="star active"><i class="icon star full"></i></span>';
                        }
                        while ($x <= 5) {
                            $html .= '<span class="star"><i class="icon star"></i></span>';
                            $x++;
                        }
                        $html .= '</div>';
                    }
                    
                    $html .= $delete;
                    $html .= '</div>';
                    $html .= '<div class="description">' . $row['body'] . '</div>';
                    $html .= '<div class="wojo horizontal divided  list align-middle actions">';
                    if ($config->rating) {
                        $html .= '<a data-up="' . $row['vote_up'] . '" data-id="' . $row['id'] . '"
						  class="item up"><span class="wojo positive text">' . $row['vote_up'] . '</span> <i class="icon chevron up"></i></a>';
                        $html .= '<a data-down="' . $row['vote_down'] . '" data-id="' . $row['id'] . '"
						  class="item down"><span class="wojo negative text">' . $row['vote_down'] . '</span> <i class="icon chevron down"></i></a>';
                    }
                    if ($parent_id == 0) {
                        $html .= '<a data-id="' . $row['id'] . '" class="item replay">' . Language::$word->CMT_REPLAY . '</a>';
                    }
                    $html .= '</div>';
                    $html .= '</div>';
                    $html .= $this->getCommentList($array, $key);
                    $html .= "</div>\n";
                }
            }
            unset($row);
            
            if ($submenu === true) {
                $html .= "</div>\n";
            }
            
            return $html;
        }
        
        /**
         * singleComment
         *
         * @param $id
         * @return int|mixed
         */
        public function singleComment($id): mixed
        {
            $sql = "
            SELECT c.id, c.user_id, c.product_id, c.parent_id, c.vote_down, c.vote_up, c.rating, c.body, c.created, c.username as uname, u.username, CONCAT(u.fname, ' ', u.lname) as name, u.avatar
              FROM `" . self::mTable . '` as c
              LEFT JOIN `' . User::mTable . '` as u ON u.id = c.user_id
              WHERE c.id = ?
            ';
            
            $row = Database::Go()->rawQuery($sql, array($id))->run();
            
            return ($row) ? : 0;
        }
        
        /**
         * render
         *
         * @param int $id
         * @return mixed
         */
        public static function render(int $id): mixed
        {
            return App::Comment()->getCommentList(App::Comment()->commentTree($id));
        }
        
        /**
         * configuration
         *
         * @return mixed
         */
        public static function configuration(): mixed
        {
            $row = json_decode(File::loadFile(ADMINBASE . '/snippets/comments.json'));
            return $row->comments;
        }
    }