<?php

namespace xmvc\core;

use xmvc\MVC;
use xmvc\Dump;
use xmvc\Queue;
use xmvc\Viewer;
use xmvc\Encoder;
use xmvc\Session;
use xmvc\core\Power;

class Cmd
{
    /** 隐藏方法退出core登录 /xmvc/core/cmd-logout , 隐藏方法 logout() 通过 xmvc\core\power的验证方法实现 */

    /**
     * index
     */
    public function index()
    {
        $menus = [];
        $contents = file_get_contents(__FILE__);
        preg_match_all('/\/\*\*(.*?)\*\/\s+public\s+function\s+([^a-zA-Z0-9_]*)([a-zA-Z0-9_]+)(?=\()/s', $contents, $m);
        if ($m) {
            foreach ((array)$m[0] as $i => $v) {
                if (strpos($v, '@menu') !== false) {
                    $pattern = '/\/\*\*\s*\*\s*(.*?)\s*@/s';
                    if (preg_match($pattern, $v, $m2)) {
                        $remark = trim($m2[1], '*');
                    }
                    $funcName = $m[3][$i];
                    $reflector = new \ReflectionMethod($this, $funcName);
                    $reflectionParameters = $reflector->getParameters();
                    $params = [];
                    if ($reflectionParameters) {
                        foreach ($reflectionParameters as $k => $pv) {
                            preg_match('/@param[^\$]+\$' . $pv->name . '\s+([^\r|\n]+)/', $v, $m3);
                            $params[$k] = new \stdClass();
                            $params[$k]->name = $pv->name;
                            $params[$k]->remark = $m3 ? $m3[1] : $pv->name;
                        }
                    }
                    $menus[] = [$funcName, $remark, $params];
                }
            }
        }
        $liArr = [];
        foreach ($menus as $v) {
            list($funcName, $remark, $params) = $v;
            if ($params) {
                $inputs = [];
                foreach ($params as $k => $pv) {
                    $inputs[] = '<span style="font-size:.8em">' . $pv->remark . ':</span> <input type="text" style="width:100%" name="' . $pv->name . '">';
                }

                $liArr[] = '<li style="padding-top:.5em;font-size:1.1em;" class="border hover">'
                . $remark . '<br />'
                . implode('<br />', $inputs)
                . ' <br />
                <a href="' . HOST . '/xmvc/core/cmd-' . $funcName . '" onclick="return bindLiInputParamValue(this)" target="_blank" style="font-size:1.1em">执行</a></li>';
            } else {
                $liArr[] = '<li style="padding-top:.5em" class="border hover"><a href="' . HOST . '/xmvc/core/cmd-' . $funcName . '" target="_blank" style="font-size:1.1em">' . $remark . '</a></li>';
            }
        }
        $liHtml = '';
        $liHtml .= '<li><a href="' . HOST . '/xmvc/core/Cmd-logout" target="_blank" style="font-size:1.1em;color:#8066A0">安全退出</a></li>';
        $liHtml .= '<li>
            帮助文档
            <ul>
                <li style="padding-left:2em"><a href="' . HOST . '/xmvc/doc/phpdoc/index-index~type-xmvc" target="_blank" style="font-size:1.1em">查看 xmvc 文档</a></li>
                <li style="padding-left:2em">-------- <a href="' . HOST . '/xmvc/doc/phpdoc/index-create~type-xmvc" target="_blank" style="font-size:1.1em">生成 xmvc 文档</a></li>
                <li style="padding-left:2em">---------------- <a href="' . HOST . '/xmvc/doc/phpdoc/index-clear~type-xmvc" target="_blank" style="font-size:1.1em">清空 xmvc 文档</a></li>
                <li style="padding-left:2em"><a href="' . HOST . '/xmvc/doc/phpdoc/index-index~type-project" target="_blank" style="font-size:1.1em">查看 ' . PROJECT . ' 文档</a></li>
                <li style="padding-left:2em">-------- <a href="' . HOST . '/xmvc/doc/phpdoc/index-create~type-project" target="_blank" style="font-size:1.1em">生成 ' . PROJECT . ' 文档</a></li>
                <li style="padding-left:2em">---------------- <a href="' . HOST . '/xmvc/doc/phpdoc/index-clear~type-project" target="_blank" style="font-size:1.1em">清空 ' . PROJECT . ' 文档</a></li>
            </ul>
        </li>';
        $liHtml .= '<li><a href="' . URL_RUNTIME . '/runtime.html" target="_blank" style="font-size:1.1em;color:#8066A0">runtime 运行时状态</a></li>';
        $liHtml .= '<li class="list0"><a href="' . HOST . '/xmvc/core/cmd-showErrorLogFile~date-' . date('Y-m-d') . '" target="_blank" style="font-size:1.1em">错误日志 ( 今天, 只取前 1024 条记录 )</a></li>';
        $liHtml .= '<li class="list0"><a href="' . HOST . '/xmvc/core/cmd-clearErrorLogFile~date-' . date('Y-m-d') . '" target="_blank" style="font-size:1.1em;color:#C00" onclick="return confirm(\'确认要备份然后清空今天的日志?\')">备份今天的日志为 Y-m-d.log.backup 然后清空今天的日志文件</a></li>';
        $liHtml .= '<li>
            控制台
            <ul>
                <li style="padding-left:2em"><a href="' . URL_RUNTIME . '/cli_dump.html" target="_blank" style="font-size:1.1em">dump(),dd() 函数输出 ( HTML 版 )</a></li>
                <li style="padding-left:2em"><a href="' . URL_RUNTIME . '/cli_dump.json" target="_blank" style="font-size:1.1em">dump(),dd() 函数输出 ( JSON 版 )</a></li>
                <li style="padding-left:2em"><a href="' . URL_RUNTIME . '/cli_error.html" target="_blank" style="font-size:1.1em">error 错误输出 ( HTML版 )</a></li>
            </ul>
        </li>';
        $liHtml .= implode('', $liArr);
        $msg = '<div style="padding:1em"><ul>{:1}</ul></div>';
        $msg = qgprintf($msg, $liHtml);
        MVC::echo($msg, true, '<title>CMD - CORE</title>');
        exit();
    }

    /**
     * PHPINFO
     * @menu
     */
    public function phpinfo()
    {
        phpinfo();
        exit();
    }

    /**
     * 站点首次运行, 初始化一些内容(例缓存目录)
     * @menu
     */
    public function runFirst()
    {
        $indexFile = ROOT . '/index.php';
        $phpCode = file_get_contents($indexFile);
        //将index配置文件中的 FIRST_RUN 修改为 true
        $phpCode = preg_replace('/define\(([\s]+)?[\'|\"]FIRST_RUN[^;]+\;/is', "define('FIRST_RUN', true);", $phpCode);
        if ($phpCode) {
            file_put_contents_lock($indexFile, $phpCode);
        }
        echo '<script>fetch("' . HTTP_HOST . '")</script>';
        MVC::alert('执行完成', '首次初始化运行');
        exit();
    }

    /**
     * 显示 常量, 配置, $_SESSION, $_SERVER
     * @menu
     */
    public function cfg()
    {
        echo '<body style="padding:1em">';

        echo '<h1>常量</h1>';
        dump(get_defined_constants(true)['user']);

        echo '<h1>配置数组</h1>';
        //echo '<p>不含数据库配置</p>';
        $db = new \xmvc\DB();
        dump(MVC::$cfg);

        echo '<h1>_SESSION</h1>';
        if (isset($_SESSION)) {
            dump('注意存在 $_SESSION', $_SESSION);
        }
        dump(Session::getAll());

        echo '<h1>_SERVER</h1>';
        dump($_SERVER);
        exit();
    }

    /**
     * 配置文件
     * @menu
     */
    public function cfgUI()
    {
        require(DIR_MVC . '/core/cmd/' . __FUNCTION__ . '.php');
        exit();
    }

    /**
     * 生成所有视图缓存, 会先清空模板缓存目录
     * @menu
     */
    public function createAllTplCacheFile()
    {
        Viewer::createAllCacheFile();
        MVC::alert('生成完成', '生成所有视图缓存');
        exit();
    }

    /**
     * 更新静态文件版本号 - 使用当前 time()
     * @menu
     */
    public function updateSVER()
    {
        $indexFile = ROOT . '/index.php';
        $phpCode = file_get_contents($indexFile);
        $phpCode = preg_replace('/define\(([\s]+)?[\'|\"]SVER[^;]+\;/is', "define('SVER', " . time() . ");", $phpCode);
        if ($phpCode) {
            file_put_contents_lock($indexFile, $phpCode);
        }
        echo '<script>fetch("' . HTTP_HOST . '")</script>';
        MVC::alert('执行完成', '更新静态文件版本号');
        exit();
    }

    /**
     * 创建一个新的类, 使用 /xmvc/core/codeTpl/class.tpl.php 样板
     *
     * @param [string] $param 目标文件目录,base64编码
     */
    public function newClass(string $param)
    {
        $tmp = base64_decode($param);
        list($filename, $function) = explode('|', $tmp);
        if (file_exists($filename)) {
            error($filename . ' 类文件已存在');
        }
        $site = getSiteNameByDir($filename);
        $site = $site ? $site : '';
        $class = filenameNotExt($filename);
        $namespace = str_replace('/', '\\', dirname(substr($filename, strlen(ROOT))));
        $tplContents = file_get_contents(DIR_MVC . '/xmvc/core/codeTpl/class.tpl.php');
        $tplContents = qgprintf($tplContents, [
            'site' => $site,
            'namespace' => $namespace,
            'class' => $class,
            'function' => $function,
        ]);
        file_put_contents($filename, $tplContents);
        chmod($filename, 0777);
        MVC::alert('已生成类文件: ' . $filename, '新的类');
        exit();
    }

    /**
     * 创建一个新的 action类, 使用 xmvc/core/codeTpl/action.tpl.php 样板
     *
     * @param [string] $param 目标文件目录,base64编码
     */
    public function newAction(string $newClassName, string $newClassFunction, string $newClassFile)
    {
        if (file_exists($newClassFile)) {
            MVC::warning($newClassFile . ' 控制器文件已存在', '存在');
            exit();
        }
        $site = getSiteNameByDir($newClassFile);
        $site = $site ? $site : '';
        $action = filenameNotExt($newClassFile);
        $namespace = substr($newClassName, 0, strlen($newClassName) - strlen($action) - 1);
        $namespace = str_replace('/', '\\', $namespace);
        $tplContents = file_get_contents(DIR_MVC . '/core/codeTpl/action.tpl.php');
        $tplContents = qgprintf($tplContents, [
            'site' => $site,
            'action' => $action,
            'namespace' => $namespace,
            'function' => $newClassFunction,
        ]);
        mkdirs(dirname($newClassFile));
        file_put_contents($newClassFile, $tplContents);
        chmod($newClassFile, 0777);
        MVC::alert('已生成控制器文件: ' . $newClassFile, '创建');
        exit();
    }

    /**
     * 创建一个新的模板文件, 使用 xmvc/core/codeTpl/tpl.tpl.php 样板
     *
     * @param [string] $param 目标文件目录,base64编码
     */
    public function newTpl(string $newClassFile)
    {
        if (file_exists($newClassFile)) {
            error($newClassFile . ' 模板文件已存在');
        }
        $site = getSiteNameByDir($newClassFile);
        $site = $site ? $site . '/' : '';
        $tplContents = file_get_contents(DIR_MVC . '/core/codeTpl/tpl.tpl.php');
        $tplContents = qgprintf($tplContents, ['site' => $site]);
        mkdirs(dirname($newClassFile));
        file_put_contents($newClassFile, $tplContents);
        chmod($newClassFile, 0777);
        MVC::alert('已生成模板文件: ' . $newClassFile, '新模板');
        exit();
    }

    /**
     * 显示 PHP 文件代码
     *
     * @param string $filename
     * @param int $line 加亮第几行
     */
    public function showPhpCode($filename, $line, $begin = 0, $end = 0, bool $return = false)
    {
        require(DIR_MVC . '/core/cmd/' . __FUNCTION__ . '.php');
        return R($code_string);
    }

    /**
     * APCu UI
     * @menu
     */
    public function apcu()
    {
        require(DIR_MVC . '/core/cmd/' . __FUNCTION__ . '.php');
        exit();
    }

    /**
     * Redis UI
     * @menu
     */
    public function redis()
    {
        require(DIR_MVC . '/core/cmd/' . __FUNCTION__ . '.php');
        exit;
    }

    /**
     * Beanstalkd 状态信息
     * @menu
     */
    public function beanstalkdStatus()
    {
        $queue = Queue::create('Beanstalk');
        $data = $queue->status();
        dump($data['tubes']);
        dump($data['status']);
        exit;
    }

    /**
     * 创建控制台密码 Hash 值, 默认 admin/Yi&parts.2008 哈希 b2add2944893de6e06a2a9fc7318a3a1
     * @param string $user 用户名
     * @param string $pass 密码
     * @menu
     */
    public function corePass($user, $pass)
    {
        $pass .= '.'; // 未尾加点号防当前面的.后面内容当成扩展名
        MVC::alert((new Power())->passwordForWWWAuth($user, $pass), $user . ' 的控制台密码如下');
        exit();
    }

    public function showErrorLogFile(string $date)
    {
        $filename = DIR_LOG . '/error/' . substr($date, 0, 4) . '/' . $date . '.log';
        $this->showLogFile($filename, 1024);
        exit();
    }

    public function showLogFile(string $filename, $maxline = 0)
    {
        if (is_file($filename)) {
            $contents = file_get_contents($filename);
            if (($fp = fopen($filename, "r")) !== false) {
                $i = 1;
                while (($line = fgets($fp))) {
                    if ($maxline > 0 && $i > $maxline) {
                        break;
                    }
                    preg_match('/\[(.*?)\]\s(.*?)\t\.\r\n/', $line, $m);
                    $date_____________________________________________________ = $m[1];
                    $josn = json_decode($m[2]);
                    dump($date_____________________________________________________);
                    dump($josn);
                    //echo $line;
                    $i++;
                }
                fclose($fp);
            }
        } else {
            MVC::echo('<div class="box-alert"><h1>NOT FOUND ' . relDir($filename) . '</h1><p>日志文件不存在</p></div>');
        }
        exit();
    }

    public function clearErrorLogFile(string $date)
    {
        $filename = DIR_LOG . '/error/' . substr($date, 0, 4) . '/' . $date . '.log';
        if (is_file($filename)) {
            $backupFilename = $filename . '.backup';
            if (!is_file($backupFilename)) {
                copy($filename, $backupFilename);
                unlink($filename);
            } else {
                MVC::echo('<div class="box-alert"><h1>EXISTS ' . relDir($backupFilename) . '</h1><p>已存在备份文件, 如要继续请手动处理.</p></div>');
            }
        } else {
            MVC::echo('<div class="box-alert"><h1>NOT FOUND ' . relDir($filename) . '</h1><p>日志文件不存在</p></div>');
        }
        exit();
    }
}
