<?php

namespace pictpostpersonal\controller\page;

use pictpostpersonal\controller\ControllerBase;

use Exception;
use pictpostpersonal\Environment;
use pictpostpersonal\Request;
use pictpostpersonal\Result;
use pictpostpersonal\SQLiteCRUD;
use pictpostpersonal\model\Article;
use pictpostpersonal\service\ThemeService;
use pictpostpersonal\Utility;

use const pictpostpersonal\TAGCLOUD_PATH;

/**
 * 
 * 検索ページ
 * 
 */
class SearchPage extends ControllerBase
{

    public function search(Request $req): ?Result
    {
        $records_per_page = 10;
        $article = new Article($this->db, $this->setting);

        try {
            $page = $req->getArgs('page', 1);
            $sort_type = $req->getArgs('sort_type', 0, Request::FILTER_INT, Request::FILTER_INT, ['min_range' => 0, 'max_range' => 7]);
            $searchs_input = $req->getArgs('q', '');
        } catch (Exception $ex) {
            //引数不正
            return new Result(400);
        }

        $sort_list = [
            ['created_at desc'],
            ['created_at asc'],
            ['updated_at desc'],
            ['updated_at asc'],
            ['views desc'],
            ['views asc'],
            ['like desc', 'created_at desc'],
            ['like asc', 'created_at desc'],
        ];
        $sort = $sort_list[$sort_type];
        $sort[] = 'id desc';


        $query = 'and hidden_at_list = 0 and status = 0 and [type] = 0';
        $conditions = [];
        if ($searchs_input != '') {
            $searchs = explode(' ', $searchs_input);
            $item_no = 0;
            foreach ($searchs as $index => $search) {
                if ($search == ':hidden') {
                    $query .= 'and hidden_at_list = true ';
                } else if ($search == ':pin') {
                    $query .= 'and pin=true ';
                } else if ($search == ':nsfw') {
                    $query .= 'and nsfw=true ';
                } else if ($search == ':fix') {
                    $query .= 'and style = 99 ';
                } else if (substr($search, 0, 1) == '#') {
                    $tag = substr($search, 1);
                    $mtag = '-' . substr($search, 1);
                    $query .= " and ( tags like :tag{$item_no} or tags like :mtag{$item_no}) ";
                    $tag = SQLiteCRUD::LikeEscape($tag);
                    $mtag = SQLiteCRUD::LikeEscape($mtag);
                    $conditions["tag{$item_no}"] = "% $tag %";
                    $conditions["mtag{$item_no}"] = "% $mtag %";
                    $item_no++;
                } else {
                    $query .= " and ( title like :item$item_no or contents like :item$item_no or tags like :item$item_no) ";
                    $search_value = SQLiteCRUD::LikeEscape($search);
                    $conditions["item{$item_no}"] = "%$search_value%";
                    $item_no++;
                }
            }
            if ($query != '') {
                //先頭の" and "を除去
                $query = substr($query, 4);
            }
        } else {
            $query = 'hidden_at_list = 0 and status = 0 and [type] = 0';
        }
        ['articles' => $articles, 'count' => $total_count] = $article->searchWithTotalCount($query, $conditions, $sort, $records_per_page, $page);
        $pages = ceil($total_count / $records_per_page);

        $nsfw_ans = $req->cookie['nsfw_ans'] ?? false;

        //データ整形
        foreach ($articles as $key => $item) {
            $articles[$key]['url'] = SITE_URL . Environment::getLogUrl($item);
            $articles[$key]['caption'] = Utility::createCaption($item['contents']);;
            $articles[$key]['created_at'] = s($item['created_at']);
            $articles[$key]['updated_at'] = s($item['updated_at']);
            $title = h($item['title']);
            $articles[$key]['title'] = $title;
            $articles[$key]['nsfw_type'] = $item['nsfw'] ? '0' : '1';
            $articles[$key]['nsfw_status'] = $nsfw_ans ? '0' : '1';
            $articles[$key]['views'] = $item['views'];
            $artilces[$key]['likes'] = $item['like'];

            $tags = explode(' ', trim($item['tags']));
            $tag_links = $this->createTagLinks($tags);
            $articles[$key]['tag_links'] = $tag_links;

            $thumbnail_class = '';
            if ($item['nsfw']) {
                $thumbnail_class .= ' thumb_nsfw';
            }
            if ($nsfw_ans) {
                $thumbnail_class .= ' thumb_nsfw_consent';
            }
            if ($item['media_count'] == 0) {
                $thumbnail_class .= ' thumb_text';
                $articles[$key]['thumbnail_title'] = $title;
            } else {
                $articles[$key]['thumbnail_title'] = '';
            }
            $articles[$key]['thumbnail_class'] = $thumbnail_class;

            $thumbnail = Utility::getThumbnailUrl($item, $nsfw_ans);
            $articles[$key]['thumbnail_path'] =  $thumbnail; //NSFW同意を考慮したサムネイル

            if ($item['media_count'] == 0) {
                $thumbnail = Utility::getThumbnailUrl($item, $nsfw_ans);
                $articles[$key]['raw_thumbnail_path'] = $thumbnail;
            } else {
                $thumbnail = Utility::getThumbnailUrl($item, true);
                $articles[$key]['raw_thumbnail_path'] = $thumbnail;
            }
        }

        //ページ選択部分
        $pagination = $this->createPagination($searchs_input, $sort_type, $page, $pages);

        $message = '';
        if ($total_count == 0) {
            if ($searchs_input == '') {
                $message = 'まだ記事は投稿されていません';
            } else {
                $message = '「' . htmlspecialchars($searchs_input) . '」に該当する記事は見つかりません';
            }
        }

        //UIレンダリング
        $template = ThemeService::getThemeTemplate('template2_search.php', $this->db, $this->setting);
        //$template = new NoSixTemplate2('template2_search.php', ["./env/templates", "./env/themes/" . $this->setting->getValue("theme", ""), "./core/templates", "./core/templates_sys"], "./env/template_cache");
        self::setSiteData($template); //サイト関連情報を設定
        self::setSystemArea($template); //管理系情報を設定

        //ページ関連情報を設定
        $template->set_data_h('page_description', '');
        $template->set_data_h('page_keywords', '');
        $template->set_data_h('page_author', $this->setting->GetValue('display_name', ''));
        $template->set_data_h('page_title', '検索結果 - ' . $this->setting->GetValue('site_title', '新しいサイト'));
        $template->set_data('page_url', SITE_URL . '/search');

        //コンテンツデータを設定
        $template->set_data('articles', $articles);
        $template->set_data('searchs', $searchs_input);
        $template->set_data('pages', $total_count / 10);
        $template->set_data('index', $page);
        $template->set_data('sort_type', $sort_type);
        $template->set_data('message', $message);

        $sort_type_select = array_fill(0, count($sort_list), '');
        $sort_type_select[$sort_type] = 'selected';

        $template->set_data('sort_type_select', $sort_type_select);

        //タグクラウド定義を読み込み
        require_once(TAGCLOUD_PATH);
        $template->set_data('tagcloud_nolink', $tagcloud_nolink);
        $template->set_data('tagcloud_nolink_more', $tagcloud_nolink_more);
        $template->set_data('tagcloud_links', $tagcloud_links);
        $template->set_data('tagcloud_links_more', $tagcloud_links_more);

        $template->set_data('pagination', $pagination);

        $output = $template->getString();

        $result = new result();
        $result->output = $output;
        return $result;
    }

    //記事のタグから検索用HTMLを作成する
    private function createTagLinks(array $tags): string
    {
        $base_url = BASE_URL;
        $tag_links = '';
        foreach ($tags as $tag) {
            if ($tag != '' && $tag[0] != '-') {
                $tag = htmlspecialchars($tag);
                $tag_links .= "<a href=\"{$base_url}/search?q=%23{$tag}\" class=\"p-tag-link\">#{$tag}</a> ";
            }
        }
        return $tag_links;
    }

    private function createPagination($searchs_input, $sort_type, $current_index, $pages)
    {
        $base_url = BASE_URL;

        $pagination = [];
        $indexer_search = '';
        if ($searchs_input) {
            $indexer_search = '&q=' . urlencode($searchs_input);
        }
        $min_page = max(1, $current_index < 5 ? 1 : $current_index - 5);
        $max_page = min($pages, $min_page + 9);

        if ($current_index >= 5) {
            $max_page = min($pages, $current_index + 5);
            $min_page = max(1, $max_page - 10);
        }

        for ($i = $min_page; $i <= $max_page; $i++) {
            if ($i == $current_index) {
                $pagination[] = ['index' => $i, 'is_current' => true, 'is_first' => $i == 1, 'is_last' => $i == $pages, 'is_page_first' => ($i == $min_page && $i != 1), 'is_page_last' => ($i == $max_page && $i != $pages), 'url' => ''];
            } else {
                $pagination[] = ['index' => $i, 'is_current' => false, 'is_first' => $i == 1, 'is_last' => $i == $pages, 'is_page_first' => ($i == $min_page && $i != 1), 'is_page_last' => ($i == $max_page && $i != $pages), 'url' => "{$base_url}/search?page={$i}{$indexer_search}&sort_type=$sort_type"];
            }
        }
        return $pagination;
    }
}
