<?php
namespace Misuzu\Satori;

use RuntimeException;
use Index\Colour\Colour;
use Index\Routing\IRouter;
use Index\Routing\IRouteHandler;
use Index\Routing\Route;
use Syokuhou\IConfig;
use Misuzu\Pagination;
use Misuzu\RoutingContext;
use Misuzu\Forum\ForumContext;
use Misuzu\Profile\ProfileFields;
use Misuzu\Users\UsersContext;

final class SatoriRoutes implements IRouteHandler {
    public function __construct(
        private IConfig $config,
        private UsersContext $usersCtx,
        private ForumContext $forumCtx,
        private ProfileFields $profileFields
    ) {}

    public function registerRoutes(IRouter $router): void {
        RoutingContext::registerSimpleErrorPages($router, '/_satori');
        Route::handleAttributes($router, $this);
    }

    #[Route('/_satori')]
    public function verifyRequest($response, $request) {
        $secretKey = $this->config->getString('secret');

        if(!empty($secretKey)) {
            $userTime = (int)$request->getHeaderLine('X-Satori-Time');
            $userHash = base64_decode((string)$request->getHeaderLine('X-Satori-Hash'));

            $currentTime = time();
            if(empty($userHash) || $userTime < $currentTime - 60 || $userTime > $currentTime + 60)
                return 403;

            $verifyText = (string)$userTime . '#' . $request->getPath() . '?' . $request->getParamString();
            $verifyHash = hash_hmac('sha256', $verifyText, $secretKey, true);

            if(!hash_equals($verifyHash, $userHash))
                return 403;
        }
    }

    #[Route('GET', '/_satori/get-profile-field')]
    public function getProfileField($response, $request): array {
        $userId = (string)$request->getParam('user', FILTER_SANITIZE_NUMBER_INT);
        $fieldId = (string)$request->getParam('field', FILTER_SANITIZE_NUMBER_INT);

        try {
            $fieldValue = $this->profileFields->getFieldValue($fieldId, $userId);
        } catch(RuntimeException $ex) {
            return ['error' => 105];
        }

        return [
            'field_value' => $fieldValue->getValue(),
        ];
    }

    #[Route('GET', '/_satori/get-recent-forum-posts')]
    public function getRecentForumPosts($response, $request): array {
        $categoryIds = $this->config->getArray('forum.categories');
        if(empty($categoryIds))
            return [];

        $batchSize = $this->config->getInteger('forum.batch', 6);
        $backlogDays = $this->config->getInteger('forum.backlog', 7);
        $startId = (string)$request->getParam('start', FILTER_SANITIZE_NUMBER_INT);

        $posts = [];
        $postInfos = $this->forumCtx->getPosts()->getPosts(
            categoryInfo: $categoryIds,
            afterPostInfo: $startId,
            newerThanDays: $backlogDays,
            pagination: new Pagination($batchSize),
            deleted: false,
        );

        foreach($postInfos as $postInfo) {
            $topicInfo = $this->forumCtx->getTopics()->getTopic(postInfo: $postInfo);
            $firstPostInfo = $this->forumCtx->getPosts()->getPost(topicInfo: $topicInfo);
            $categoryInfo = $this->forumCtx->getCategories()->getCategory(topicInfo: $topicInfo);
            $userInfo = $postInfo->hasUserId() ? $this->usersCtx->getUserInfo($postInfo->getUserId()) : null;
            $userColour = $this->usersCtx->getUserColour($userInfo);

            $posts[] = [
                'post_id' => (int)$postInfo->getId(),
                'topic_id' => (int)$topicInfo->getId(),
                'topic_title' => $topicInfo->getTitle(),
                'forum_id' => (int)$categoryInfo->getId(),
                'forum_name' => $categoryInfo->getName(),
                'user_id' => (int)$userInfo->getId(),
                'username' => $userInfo->getName(),
                'user_colour' => Colour::toMisuzu($userColour),
                'is_opening_post' => $postInfo->getId() === $firstPostInfo->getId() ? 1 : 0,
            ];
        }

        return $posts;
    }

    #[Route('GET', '/_satori/get-recent-registrations')]
    public function getRecentRegistrations($response, $request) {
        $batchSize = $this->config->getInteger('users.batch', 10);
        $backlogDays = $this->config->getInteger('users.backlog', 7);
        $startId = (string)$request->getParam('start', FILTER_SANITIZE_NUMBER_INT);

        $userInfos = $this->usersCtx->getUsers()->getUsers(
            after: $startId,
            newerThanDays: $backlogDays,
            orderBy: 'id',
            pagination: new Pagination($batchSize),
            deleted: false
        );

        $users = [];

        foreach($userInfos as $userInfo)
            $users[] = [
                'user_id' => (int)$userInfo->getId(),
                'username' => $userInfo->getName(),
            ];

        return $users;
    }
}
