<?php

namespace pictpostpersonal\controller\page;

use pictpostpersonal\controller\ControllerBase;

use Exception;
use pictpostpersonal\Authentification;
use pictpostpersonal\Environment;
use pictpostpersonal\Request;
use pictpostpersonal\Result;
use pictpostpersonal\SQLiteCRUD;
use pictpostpersonal\model\Article;
use pictpostpersonal\model\Message;
use pictpostpersonal\NoSixTemplate2;
use pictpostpersonal\Utility;

use const pictpostpersonal\TAGCLOUD_PATH;

class ConsolePage extends ControllerBase
{
    /**
     * コンソールページ：記事一覧を表示する
     *  HTTP引数：
     *      page     : 1～ 記事が規定数を超えている場合の表示ページ番号。省略時は1扱い。
     *      query    : 絞り込み用文字列。スペース区切りで条件を渡す。
     *      sort_type: 0～ 並び替えタイプ。数字と並び替えの組み合わせはソース参照。
     *
     * @param Request $req
     * 
     * @return Result|null
     * 
     */
    public function showArticleList(Request $req): ?Result
    {

        $records_per_page = 10;
        $article = new Article($this->db, $this->setting);
        $page = $req->getArgs('page', 1);
        $searchs_input = $req->getArgs('q', '');
        $sort_type = $req->getArgs('sort_type', '0');
        $sort_list = [
            ['created_at desc'],
            ['created_at asc', 'updated_at desc'],
            ['updated_at asc'],
            ['updated_at desc'],
            ['views desc', 'created_at desc'],
            ['views asc', 'created_at desc'],
            ['like desc', 'created_at desc'],
            ['like asc', 'created_at desc'],
        ];
        $sort = $sort_list[$sort_type];
        $sort[] = 'id desc';

        $query = 'and ([type] = 0 or [type] = 1) ';
        $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 == ':draft') {
                    $query .= 'and status=1 ';
                } 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);
        }
        ['articles' => $articles, 'count' => $total_count] = $article->searchWithTotalCount($query, $conditions, $sort, $records_per_page, $page);
        $pages = ceil($total_count / $records_per_page);

        //データ整形
        foreach ($articles as $key => $item) {
            $caption = Utility::createCaption($item['contents']);
            $articles[$key]['caption'] = $caption;
            $articles[$key]['title'] = h($item['title']);
            $articles[$key]['created_at'] = s($item['created_at']);
            $thumbnail = Utility::getThumbnailUrl($item, true);
            $articles[$key]['thumbnail'] = $thumbnail;
        }

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

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

        //UIレンダリング
        $template = new NoSixTemplate2('template2_console_articles2.php', ['./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('articles', $articles);
        $template->set_data_h('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('pagination', $pagination);

        $output = $template->getString();

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


    /**
     * 指定されたIDの記事を削除する。JSONで応答する。
     *
     * @param Request $req
     * 
     * @return Result|null
     * 
     */
    public function deleteArticleAPI(Request $req): ?Result
    {
        if (!$this->auth->isLogin()) {
            //ログインしていない場合はエラー応答
            return new Result(400, "{\"status\":\"error\", \"message\":\"ログインが必要です\"}");
        }

        //引数チェック
        $target = $req->getArgs('target', '-1');
        if ($target == '-1') {
            return new Result(400, '引数が不正です');
        }

        //削除実行
        $article = new Article($this->db, $this->setting);
        try {
            $article->deleteByIDList([$target]);
        } catch (Exception $ex) {
            return new Result(500, '削除に失敗しました');
        }

        return new Result(400, "{\"status\":\"success\", \"message\":\"削除しました\"}");
    }



    /**
     * コンソールページ：メッセージ一覧を表示する
     *  HTTP引数：
     *      page     : 1～ 記事が規定数を超えている場合の表示ページ番号。省略時は1扱い。
     *      query    : 絞り込み用文字列。スペース区切りで条件を渡す。
     *      sort_type: 0～ 並び替えタイプ。数字と並び替えの組み合わせはソース参照。
     *
     * @param Request $req
     * 
     * @return Result|null
     * 
     */
    public function showMessageList(Request $req): ?Result
    {
        $records_per_page = 10;
        $message_cls = new Message($this->db, $this->setting);
        $page = $req->getArgs('page', 1);
        $searchs_input = $req->getArgs('q', '');
        $sort_type = $req->getArgs('sort_type', '0');
        $sort_list = [
            'created_at desc',
            'created_at asc',
            'name desc',
            'name asc',
            'from_ip desc',
            'from_ip asc',
        ];
        $sort = $sort_list[$sort_type];

        $query = '';
        $conditions = [];
        if ($searchs_input != '') {
            $searchs = explode(' ', $searchs_input);
            $item_no = 0;
            foreach ($searchs as $index => $search) {
                $query .= " and ( email like :item$item_no or message like :item$item_no or name like :item$item_no) ";
                $search_value = SQLiteCRUD::LikeEscape($search);
                $conditions["item{$item_no}"] = "%$search_value%";
                $item_no++;
            }
            if ($query != '') {
                //先頭の" and "を除去
                $query = substr($query, 4);
            }
        }

        [$messages, $total_count] = $message_cls->searchWithTotalCount($query, $conditions, $sort, $records_per_page, $page - 1);
        $pages = ceil($total_count / $records_per_page);

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

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

        //データ整形
        foreach ($messages as $key => $item) {
            //HTMLタグを除去する
            $convert_message = Utility::convertLineBreaks(htmlspecialchars(strip_tags($item['message'] ?? '')));
            $messages[$key]['message'] = $convert_message;
            $messages[$key]['name'] = htmlspecialchars(strip_tags($item['name'] ?? ''));
            $messages[$key]['email'] = htmlspecialchars(strip_tags($item['email'] ?? ''));

            $caption = Utility::createCaption($convert_message);
            $messages[$key]['caption'] = $caption;
            if (Environment::isDemoMode()) {
                $messages[$key]['from_ip'] = '0.0.0.0';
                $messages[$key]['email']  = 'sample@example.com';
            }
        }

        //UIレンダリング
        $site_url = SITE_URL;
        $template = new NoSixTemplate2('template2_console_message2.php', ['./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('articles', $messages);
        $template->set_data_h('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('messages', $messages);
        $template->set_data('message', $warn_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);
        $template->set_data('pagination', $pagination);

        $output = $template->getString();

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

    private function createPagination($target, $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}/console/{$target}?page={$i}{$indexer_search}&sort_type=$sort_type"];
            }
        }
        return $pagination;
    }
}
