<?php
/**
 * Created by PhpStorm.
 * User: 中闽 < 1464674022@qq.com >
 * Date: 2019/12/5
 * Time: 17:44
 */

namespace app\admin\controller;

use app\admin\controller\base\Permissions;
use file\FileHelper;
use think\Db;

class CodeGeneration extends Permissions
{
    /**
     * @return mixed
     */
    public function index()
    {
        $dbName = \think\Env::get("db_name", "");
        $prefix = \think\Env::get("db_prefix", "");
        //排除核心表
        $coreTables = ['admin', 'admin_cate', 'admin_log', 'admin_menu', 'urlconfig', 'webconfig', 'smsconfig', 'emailconfig', 'config', 'config_option', 'config_tab', 'catalog', 'cate_catalog'];
        $filters = [];
        foreach ($coreTables as $table) {
            $filters[] = "'{$prefix}{$table}'";
        }
        $filter = implode(',', $filters);

        $tables = Db::query("SELECT TABLE_NAME,TABLE_COMMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=? AND TABLE_NAME NOT IN ($filter)", [$dbName]);
        $this->assign('tables', $tables);
        return $this->fetch();
    }

    /**
     * 获取字段信息
     * @return array
     */
    public function getFieldsInfo()
    {
        if ($this->request->isAjax()) {
            $post = $this->request->param();
            $validate = new \think\Validate([
                ['table', 'require|max:50', '请选择数据库表'],
            ]);
            if (!$validate->check($post)) {
                $this->error('提交失败：' . $validate->getError());
            }
            $nameAndComment = explode('|', $post['table']);
            $tableName = $nameAndComment[0]??'';
            $data = $this->getFieldsInfoByTableName($tableName);
            return array('code' => 0, 'count' => count($data), 'data' => $data);
        }
    }

    /**
     * 生成
     */
    public function generation()
    {
        $post = $this->request->post();
        if ($this->request->isPost()) {
            $validate = new \think\Validate([
                ['table', 'require|max:50', '请选择数据库表'],
            ]);
            if (!$validate->check($post)) {
                $this->error('提交失败：' . $validate->getError());
            }
        }

        $nameAndComment = explode('|', $post['table']);
        $tableName = $nameAndComment[0]??'';
        $menuName = $nameAndComment[1] ?: $tableName;
        $humpName = $this->getHumpName($tableName);
        $underLineName = $this->getUnderLineName($tableName);

        $fieldsInfo = $this->getFieldsInfoByTableName($tableName);
        foreach ($fieldsInfo as $k => $item) {
            $field = $item['Field'];
            $fieldsInfo[$k]["ShowList"] = $post[$field . "_ShowList"]??'';
            $fieldsInfo[$k]["ShowSearch"] = $post[$field . "_ShowSearch"]??'';
            $fieldsInfo[$k]["ShowEdit"] = $post[$field . "_ShowEdit"]??'';
            $fieldsInfo[$k]["Component"] = $post[$field . "_Component"];
        }

        $tpData = [
            'fieldsInfo' => $fieldsInfo,
            'humpName' => $humpName,
            'underLineName' => $underLineName,
            'menuName' => $menuName,
            'tableName' => $tableName,
            'crud' => $post['crud']??[],
        ];


        //模板文件目录
        $tpdir = APP_PATH . 'admin' . DS . 'view' . DS . 'code_generation' . DS . 'tpl' . DS;
        //生成文件路径
        $ControllerPath = APP_PATH . 'admin' . DS . 'controller' . DS . $humpName . '.php';
        $ModelPath = APP_PATH . 'common' . DS . 'model' . DS . $humpName . '.php';
        $IndexPath = APP_PATH . 'admin' . DS . 'view' . DS . $underLineName . DS . 'index.html';
        $PublishPaht = APP_PATH . 'admin' . DS . 'view' . DS . $underLineName . DS . 'publish.html';

        if (!$this->request->has('cover')) {
            //检查文件是否已存在
            $checkMsg = "";
            if (file_exists($ControllerPath)) {
                $checkMsg .= str_replace(APP_PATH, '', $ControllerPath) . " 已存在" . '</br>';
            }
            if (file_exists($ModelPath)) {
                $checkMsg .= str_replace(APP_PATH, '', $ModelPath) . " 已存在" . '</br>';
            }
            if (file_exists($IndexPath)) {
                $checkMsg .= str_replace(APP_PATH, '', $IndexPath) . " 已存在" . '</br>';
            }
            if (array_key_exists('update', $tpData['crud']) or array_key_exists('create', $tpData['crud'])) {
                if (file_exists($PublishPaht)) {
                    $checkMsg .= str_replace(APP_PATH, '', $PublishPaht) . " 已存在" . '</br>';
                }
            }
            if (!empty($checkMsg)) {
                $checkMsg .= "<span style='color:red;'>确认生成并覆盖？</span>";
                $this->error($checkMsg);
            }
        }


        //生成controller
        $content = $this->fetch($tpdir . 'AdminController.php.tp', $tpData);
        FileHelper::save($ControllerPath, "<?php" . PHP_EOL . $content);

        //生成model
        $content = $this->fetch($tpdir . 'Model.php.tp', $tpData);
        FileHelper::save($ModelPath, "<?php" . PHP_EOL . $content);

        //生成index.html
        $content = $this->fetch($tpdir . 'index.html.tp', $tpData);
        FileHelper::save($IndexPath, $content);

        //生成publish.html
        if (array_key_exists('update', $tpData['crud']) or array_key_exists('create', $tpData['crud'])) {
            $content = $this->fetch($tpdir . 'publish.html.tp', $tpData);
            FileHelper::save($PublishPaht, $content);
        }

        $this->success("success");
    }

    /**
     * 表名 转 驼峰命名
     * @param $tableName
     * @return string
     */
    protected function getHumpName($tableName)
    {
        $db_prefix = \think\Env::get("db_prefix", "");
        //去除表前缀
        $tableName = str_replace($db_prefix, '', $tableName);
        //拆分，首字母大写
        $trems = explode('_', $tableName);
        $controllerName = "";
        foreach ($trems as $trem) {
            $controllerName .= ucfirst($trem);
        }
        return $controllerName ?: 'DefaultController';
    }

    /**
     * 表名 转 下划线命名
     * @param $tableName
     * @return mixed
     */
    protected function getUnderLineName($tableName)
    {
        //去除表前缀即可
        $db_prefix = \think\Env::get("db_prefix", "");
        return str_replace($db_prefix, '', $tableName);
    }

    /**
     * 获取字段信息
     * @param $tableName
     * @return array
     */
    protected function getFieldsInfoByTableName($tableName)
    {
        $dbName = \think\Env::get("db_name", "");
        //读取字段信息
        $infos = Db::query("desc " . $tableName);

        //读取字段注释
        $comments = Db::query("SELECT COLUMN_NAME,column_comment FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME=? AND table_schema=?", [$tableName, $dbName]);

        $data = [];
        foreach ($infos as $k => $info) {
            $data[$info['Field']] = $info;
            $data[$info['Field']]['Comment'] = $comments[$k]['column_comment'];//这里不能保证两个数组顺序一致，后期有问题再修改
        }
        return $data;
    }
}