<?php
namespace Misuzu;

use stdClass;
use RuntimeException;
use Index\XArray;
use Misuzu\Comments\CommentsCategory;

if(!$msz->isLoggedIn())
    Template::throwError(403);

$searchQuery = !empty($_GET['q']) && is_string($_GET['q']) ? $_GET['q'] : '';

$searchQueryEvaluated = ['query' => []];
Template::addFunction('search_merge_query', function($attrs) use (&$searchQueryEvaluated) {
    $existing = [];

    if(!empty($attrs['type']))
        $existing[] = 'type:' . $attrs['type'];
    elseif(!empty($searchQueryEvaluated['type']))
        $existing[] = 'type:' . $searchQueryEvaluated['type'];

    if(!empty($attrs['author']))
        $existing[] = 'author:' . $attrs['author'];
    elseif(!empty($searchQueryEvaluated['author']))
        $existing[] = 'author:' . $searchQueryEvaluated['author']->getName();

    if(!empty($attrs['after']))
        $existing[] = 'after:' . $attrs['after'];
    elseif(!empty($searchQueryEvaluated['after']))
        $existing[] = 'after:' . $searchQueryEvaluated['after'];

    $existing = array_merge($existing, array_unique(array_merge(
        $searchQueryEvaluated['query'],
        empty($attrs['query']) ? [] : explode(' ', $attrs['query'])
    )));

    return rawurlencode(implode(' ', $existing));
});
if(!empty($searchQuery)) {
    $users = $msz->getUsers();
    $forum = $msz->getForum();
    $news = $msz->getNews();
    $comments = $msz->getComments();

    $userInfos = [];
    $userColours = [];

    $searchQueryAttributes = ['type', 'author', 'after'];
    $searchQueryParts = explode(' ', $searchQuery);
    foreach($searchQueryParts as $queryPart) {
        $queryPart = trim($queryPart);
        if($queryPart === '')
            continue;

        $colonIndex = strpos($queryPart, ':');
        if($colonIndex !== false && $colonIndex > 0) {
            $attrName = substr($queryPart, 0, $colonIndex);
            if(in_array($attrName, $searchQueryAttributes)) {
                $attrValue = substr($queryPart, $colonIndex + 1);
                $searchQueryEvaluated[$attrName] = $attrValue;
                continue;
            }
        }

        $searchQueryEvaluated['query'][] = $queryPart;
    }

    $searchQueryEvaluated['query_string'] = implode(' ', $searchQueryEvaluated['query']);

    if(!empty($searchQueryEvaluated['author']))
        try {
            $searchQueryEvaluated['author'] = $users->getUser($searchQueryEvaluated['author'], 'search');
        } catch(RuntimeException $ex) {
            unset($searchQueryEvaluated['author']);
        }

    if(empty($searchQueryEvaluated['type']) || str_starts_with($searchQueryEvaluated['type'], 'forum')) {
        $currentUser = $msz->getActiveUser();
        $currentUserId = $currentUser === null ? 0 : (int)$currentUser->getId();

        $forumCategoryIds = XArray::where(
            $forum->getCategories(hidden: false),
            fn($categoryInfo) => $categoryInfo->mayHaveTopics() && $msz->getAuthInfo()->getPerms('forum', $categoryInfo)->check(Perm::F_CATEGORY_VIEW)
        );

        $forumTopicInfos = $forum->getTopics(categoryInfo: $forumCategoryIds, deleted: false, searchQuery: $searchQueryEvaluated);
        $forumTopics = [];

        foreach($forumTopicInfos as $topicInfo) {
            $forumTopics[] = $topic = new stdClass;
            $topic->info = $topicInfo;
            $topic->unread = $forum->checkTopicUnread($topicInfo, $currentUser);
            $topic->participated = $forum->checkTopicParticipated($topicInfo, $currentUser);
            $topic->lastPost = new stdClass;

            if($topicInfo->hasUserId()) {
                $lastTopicUserId = $topicInfo->getUserId();
                if(!array_key_exists($lastTopicUserId, $userInfos)) {
                    $userInfo = $users->getUser($lastTopicUserId, 'id');
                    $userInfos[$lastTopicUserId] = $userInfo;
                    $userColours[$lastTopicUserId] = $users->getUserColour($userInfo);
                }

                $topic->user = $userInfos[$lastTopicUserId];
                $topic->colour = $userColours[$lastTopicUserId];
            }

            try {
                $topic->lastPost->info = $lastPostInfo = $forum->getPost(
                    topicInfo: $topicInfo,
                    getLast: true,
                    deleted: $topicInfo->isDeleted() ? null : false,
                );

                if($lastPostInfo->hasUserId()) {
                    $lastPostUserId = $lastPostInfo->getUserId();
                    if(!array_key_exists($lastPostUserId, $userInfos)) {
                        $userInfo = $users->getUser($lastPostUserId, 'id');
                        $userInfos[$lastPostUserId] = $userInfo;
                        $userColours[$lastPostUserId] = $users->getUserColour($userInfo);
                    }

                    $topic->lastPost->user = $userInfos[$lastPostUserId];
                    $topic->lastPost->colour = $userColours[$lastPostUserId];
                }
            } catch(RuntimeException $ex) {}
        }

        $forumPostInfos = $forum->getPosts(categoryInfo: $forumCategoryIds, searchQuery: $searchQueryEvaluated);
        $forumPosts = [];

        foreach($forumPostInfos as $postInfo) {
            $forumPosts[] = $post = new stdClass;
            $post->info = $postInfo;

            if($postInfo->hasUserId()) {
                $postUserId = $postInfo->getUserId();
                if(!array_key_exists($postUserId, $userInfos)) {
                    $userInfo = $users->getUser($postUserId, 'id');
                    $userInfos[$postUserId] = $userInfo;
                    $userColours[$postUserId] = $users->getUserColour($userInfo);
                    $userPostsCounts[$postUserId] = $forum->countPosts(userInfo: $userInfo, deleted: false);
                }

                $post->user = $userInfos[$postUserId];
                $post->colour = $userColours[$postUserId];
                $post->postsCount = null;
            }

            // can't be bothered sorry
            $post->isOriginalPost = false;
            $post->isOriginalPoster = false;
        }
    }

    $newsPosts = [];
    $newsPostInfos = empty($searchQueryEvaluated['type']) || $searchQueryEvaluated['type'] === 'news' ? $news->getPosts(searchQuery: $searchQuery) : [];
    $newsCategoryInfos = [];

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

        if(array_key_exists($userId, $userInfos)) {
            $userInfo = $userInfos[$userId];
        } else {
            try {
                $userInfo = $users->getUser($userId, 'id');
                $userColours[$userId] = $users->getUserColour($userInfo);
            } catch(RuntimeException $ex) {
                $userInfo = null;
            }

            $userInfos[$userId] = $userInfo;
        }

        if(array_key_exists($categoryId, $newsCategoryInfos))
            $categoryInfo = $newsCategoryInfos[$categoryId];
        else
            $newsCategoryInfos[$categoryId] = $categoryInfo = $news->getCategory(postInfo: $postInfo);

        $commentsCount = $postInfo->hasCommentsCategoryId()
            ? $comments->countPosts(categoryInfo: $postInfo->getCommentsCategoryId(), deleted: false) : 0;

        $newsPosts[] = [
            'post' => $postInfo,
            'category' => $categoryInfo,
            'user' => $userInfo,
            'user_colour' => $userColours[$userId] ?? \Index\Colour\Colour::none(),
            'comments_count' => $commentsCount,
        ];
    }

    $members = [];
    $memberInfos = $users->getUsers(searchQuery: $searchQueryEvaluated);

    foreach($memberInfos as $memberInfo) {
        $members[] = $member = new stdClass;
        $member->info = $memberInfo;

        $memberId = $memberInfo->getId();
        if(!array_key_exists($memberId, $userColours))
            $userColours[$memberId] = $users->getUserColour($memberId);

        $member->colour = $userColours[$memberId];
        $member->ftopics = $forum->countTopics(userInfo: $memberInfo, deleted: false);
        $member->fposts = $forum->countPosts(userInfo: $memberInfo, deleted: false);
    }
}

Template::render('home.search', [
    'search_query' => $searchQuery,
    'forum_topics' => $forumTopics ?? [],
    'forum_posts' => $forumPosts ?? [],
    'members' => $members ?? [],
    'news_posts' => $newsPosts ?? [],
]);
