<?php
namespace Misuzu\Http\Handlers;

use RuntimeException;
use Misuzu\DB;
use Misuzu\Pagination;
use Misuzu\Template;
use Misuzu\Comments\CommentsCategory;
use Misuzu\Users\User;
use Misuzu\Users\UserSession;

final class HomeHandler extends Handler {
    public function index($response, $request): void {
        if(UserSession::hasCurrent())
            $this->home($response, $request);
        else
            $this->landing($response, $request);
    }

    public function landing($response, $request): void {
        $config = $this->context->getConfig();

        if($config->getBoolean('social.embed_linked')) {
            $ldr = $config->getValues([
                ['site.name:s', 'Misuzu'],
                'site.url:s',
                'site.ext_logo:s',
                'social.linked:a'
            ]);
            $linkedData = [
                'name' => $ldr['site.name'],
                'url' => $ldr['site.url'],
                'logo' => $ldr['site.ext_logo'],
                'same_as' => $ldr['social.linked'],
            ];
        } else $linkedData = null;

        $featuredNews = $this->context->getNews()->getAllPosts(
            onlyFeatured: true,
            pagination: new Pagination(3)
        );

        $stats = DB::query(
            'SELECT'
            . ' (SELECT COUNT(`user_id`) FROM `msz_users` WHERE `user_deleted` IS NULL) AS `count_users_all`,'
            . ' (SELECT COUNT(`user_id`) FROM `msz_users` WHERE `user_active` >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)) AS `count_users_online`,'
            . ' (SELECT COUNT(`user_id`) FROM `msz_users` WHERE `user_active` >= DATE_SUB(NOW(), INTERVAL 24 HOUR)) AS `count_users_active`,'
            . ' (SELECT COUNT(`comment_id`) FROM `msz_comments_posts` WHERE `comment_deleted` IS NULL) AS `count_comments`,'
            . ' (SELECT COUNT(`topic_id`) FROM `msz_forum_topics` WHERE `topic_deleted` IS NULL) AS `count_forum_topics`,'
            . ' (SELECT COUNT(`post_id`) FROM `msz_forum_posts` WHERE `post_deleted` IS NULL) AS `count_forum_posts`'
        )->fetch();

        $onlineUsers = DB::query(
            'SELECT u.`user_id`, u.`username`, COALESCE(u.`user_colour`, r.`role_colour`) AS `user_colour`'
            . ' FROM `msz_users` AS u'
            . ' LEFT JOIN `msz_roles` AS r'
            . ' ON r.`role_id` = u.`display_role`'
            . ' WHERE u.`user_active` >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)'
            . ' ORDER BY u.`user_active` DESC, RAND()'
            . ' LIMIT 100'
        )->fetchAll();

        // TODO: don't hardcode forum ids
        $featuredForums = $config->getArray('landing.forum_categories');

        $popularTopics = [];
        $activeTopics = [];

        if(!empty($featuredForums)) {
            $getPopularTopics = DB::prepare(
                'SELECT t.`topic_id`, c.`forum_id`, t.`topic_title`, c.`forum_icon`, t.`topic_count_views`'
                . ', (SELECT COUNT(*) FROM `msz_forum_posts` AS p WHERE p.`topic_id` = t.`topic_id` AND `post_deleted` IS NULL) AS `topic_count_posts`'
                . ' FROM `msz_forum_topics` AS t'
                . ' LEFT JOIN `msz_forum_categories` AS c ON c.`forum_id` = t.`forum_id`'
                . ' WHERE c.`forum_id` IN (' . implode(',', $featuredForums) . ') AND `topic_deleted` IS NULL AND `topic_locked` IS NULL'
                . ' ORDER BY (SELECT COUNT(*) FROM `msz_forum_posts` AS p WHERE p.`topic_id` = t.`topic_id` AND `post_deleted` IS NULL AND `post_created` > NOW() - INTERVAL 3 MONTH) DESC'
            )->stmt;
            $getPopularTopics->execute();
            for($i = 0; $i < 10; ++$i) {
                $topicInfo = $getPopularTopics->fetchObject();
                if(empty($topicInfo))
                    break;
                $popularTopics[] = $topicInfo;
            }

            $getActiveTopics = DB::prepare(
                'SELECT t.`topic_id`, c.`forum_id`, t.`topic_title`, c.`forum_icon`, t.`topic_count_views`'
                . ', (SELECT COUNT(*) FROM `msz_forum_posts` AS p WHERE p.`topic_id` = t.`topic_id` AND `post_deleted` IS NULL) AS `topic_count_posts`'
                . ', (SELECT MAX(`post_id`) FROM `msz_forum_posts` AS p WHERE p.`topic_id` = t.`topic_id` AND `post_deleted` IS NULL) AS `latest_post_id`'
                . ' FROM `msz_forum_topics` AS t'
                . ' LEFT JOIN `msz_forum_categories` AS c ON c.`forum_id` = t.`forum_id`'
                . ' WHERE c.`forum_id` IN (' . implode(',', $featuredForums) . ') AND `topic_deleted` IS NULL AND `topic_locked` IS NULL'
                . ' ORDER BY `topic_bumped` DESC'
            )->stmt;
            $getActiveTopics->execute();
            for($i = 0; $i < 10; ++$i) {
                $topicInfo = $getActiveTopics->fetchObject();
                if(empty($topicInfo))
                    break;
                $activeTopics[] = $topicInfo;
            }
        }

        $response->setContent(Template::renderRaw('home.landing', [
            'statistics' => $stats,
            'online_users' => $onlineUsers,
            'featured_news' => $featuredNews,
            'linked_data' => $linkedData,
            'forum_popular' => $popularTopics,
            'forum_active' => $activeTopics,
        ]));
    }

    public function home($response, $request): void {
        $news = $this->context->getNews();
        $comments = $this->context->getComments();
        $featuredNews = [];
        $userInfos = [];
        $categoryInfos = [];
        $featuredNewsInfos = $news->getAllPosts(
            onlyFeatured: true,
            pagination: new Pagination(5)
        );

        foreach($featuredNewsInfos as $postInfo) {
            $userId = $postInfo->getUserId();
            $categoryId = $postInfo->getCategoryId();

            if(array_key_exists($userId, $userInfos)) {
                $userInfo = $userInfos[$userId];
            } else {
                try {
                    $userInfo = User::byId($userId);
                } catch(RuntimeException $ex) {
                    $userInfo = null;
                }

                $userInfos[$userId] = $userInfo;
            }

            if(array_key_exists($categoryId, $categoryInfos))
                $categoryInfo = $categoryInfos[$categoryId];
            else
                $categoryInfos[$categoryId] = $categoryInfo = $news->getCategoryByPost($postInfo);

            $commentsCount = $postInfo->hasCommentsCategoryId()
                ? $comments->countPosts($postInfo->getCommentsCategoryId(), includeReplies: true) : 0;

            $featuredNews[] = [
                'post' => $postInfo,
                'category' => $categoryInfo,
                'user' => $userInfo,
                'comments_count' => $commentsCount,
            ];
        }

        $stats = DB::query(
            'SELECT'
            . ' (SELECT COUNT(`user_id`) FROM `msz_users` WHERE `user_deleted` IS NULL) AS `count_users_all`,'
            . ' (SELECT COUNT(`user_id`) FROM `msz_users` WHERE `user_active` >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)) AS `count_users_online`,'
            . ' (SELECT COUNT(`user_id`) FROM `msz_users` WHERE `user_active` >= DATE_SUB(NOW(), INTERVAL 24 HOUR)) AS `count_users_active`,'
            . ' (SELECT COUNT(`comment_id`) FROM `msz_comments_posts` WHERE `comment_deleted` IS NULL) AS `count_comments`,'
            . ' (SELECT COUNT(`topic_id`) FROM `msz_forum_topics` WHERE `topic_deleted` IS NULL) AS `count_forum_topics`,'
            . ' (SELECT COUNT(`post_id`) FROM `msz_forum_posts` WHERE `post_deleted` IS NULL) AS `count_forum_posts`'
        )->fetch();

        $changelog = $this->context->getChangelog()->getAllChanges(pagination: new Pagination(10));

        $birthdays  = User::byBirthdate();
        $latestUser = !empty($birthdays) ? null : User::byLatest();

        $onlineUsers = DB::query(
            'SELECT u.`user_id`, u.`username`, COALESCE(u.`user_colour`, r.`role_colour`) AS `user_colour`'
            . ' FROM `msz_users` AS u'
            . ' LEFT JOIN `msz_roles` AS r'
            . ' ON r.`role_id` = u.`display_role`'
            . ' WHERE u.`user_active` >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)'
            . ' ORDER BY u.`user_active` DESC, RAND()'
            . ' LIMIT 104'
        )->fetchAll();

        $response->setContent(Template::renderRaw('home.home', [
            'statistics' => $stats,
            'latest_user' => $latestUser,
            'online_users' => $onlineUsers,
            'birthdays' => $birthdays,
            'featured_changelog' => $changelog,
            'featured_news' => $featuredNews,
        ]));
    }
}
