<?php

namespace app\admin\controller\Gen\GenApi;

use app\admin\controller\Gen\Gen;

/**
 * 后端生成类
 */
class GenApi
{
    /**
     * 项目根目录路径
     * @var string
     */
    protected $root;

    /**
     * 字段信息
     * @var array
     */
    protected $fields = [];

    /**
     * 生成信息
     * @var array
     */
    protected $table = [];

    /**
     * 实体类名
     * @var string 例：User
     */
    protected $class_name;

    /**
     * 模块名
     * @var string 例：User
     */
    protected $module_name;

    /**
     * 业务名 例：user
     * @var string 
     */
    protected $business_name;

    /**
     * 方法名
     * @var string 例：用户
     */
    protected $function_name;

    /**
     * 后端生成模板文件路径配置
     * @var array
     */
    protected const TEMP_PATH_CONFIG = [
        'crud' => [ //单表(增删改查)
            'api' => 'resources/view/api/controller.tpl',
            'admin' => 'resources/view/admin/controller.tpl',
            'model' => 'resources/view/admin/model.tpl',
        ],
        'crud_sort' => [ //单表(增删改查+排序处理)
            'api' => 'resources/view/api/controller.tpl',
            'admin' => 'resources/view/business/sort/sortAdminController.tpl',
            'model' => 'resources/view/business/sort/sortModel.tpl',
        ],
        'web_static' => [ //门户静态
            'api' => 'resources/view/business/webApiController.tpl',
            'admin' => 'resources/view/business/webController.tpl',
            'model' => 'resources/view/admin/model.tpl',
        ],
    ];

    /**
     * 模型层模板读取路径
     * @var string
     */
    protected $model_temp_path;

    /**
     * 模型层模块生成路径
     * @var string
     */
    protected $model_module_path;

    /**
     * 模型层生成路径
     * @var string
     */
    protected $model_path;

    /**
     * 后台控制器模板读取路径
     * @var string
     */
    protected $admin_con_temp_path;

    /**
     * 后台控制器模块生成路径
     * @var string
     */
    protected $admin_con_module_path;

    /**
     * 后台控制器生成路径
     * @var string
     */
    protected $admin_con_path;

    /**
     * 前台控制器模板读取路径
     * @var string
     */
    protected $api_con_temp_path;

    /**
     * 前台控制器生成路径
     * @var string
     */
    protected $api_con_path;

    /**
     * 前台控制器模块生成路径
     * @var string
     */
    protected $api_con_module_path;

    /**
     * 新增功能必要字段
     * @var array
     */
    protected $add_required_fields = ['guid', 'create_user_guid', 'update_user_guid'];

    /**
     * 新增允许字段模板字符串
     * @var string 例:['user_name','user_id',...]
     */
    protected $add_fields_temp;

    /**
     * 新增必填验证模板字符串
     * @var string 例: ['user_name|用户名称' => 'require',...]
     */
    protected $add_required_verify_temp;

    /**
     * 修改功能必要字段
     * @var array
     */
    protected $edit_required_fields = ['update_user_guid'];

    /**
     * 编辑允许字段模板字符串
     * @var string 例:['user_name','user_id',...]
     */
    protected $edit_fields_temp;

    /**
     * 编辑必填验证模板字符串
     * @var string 例: ['user_name|用户名称' => 'require',...]
     */
    protected $edit_required_verify_temp;

    /**
     * 业务字段
     * @var array 例:[ 'user_name' => '用户名称',...]
     */
    protected $business_fields = [];

    /**
     * 是否导入
     * @var bool
     */
    protected $is_import = false;

    /**
     * 是否导出
     * @var bool
     */
    protected $is_export = false;

    /**
     * 是否排序处理
     * @var bool
     */
    protected $is_sort = false;

    /**
     * 图片字段数组
     * @var array
     */
    protected $img_fields = [];

    /**
     * 生成后端模板类型
     * @var string crud:: 单表(增删改查) | web_static: 门户静态模块(查询修改)
     */
    protected $gen_api_type;

    /**
     * 查询列表显示字段
     * @var array 例:['user_name','user_id',...]
     */
    protected $query_list_fields = [];

    /**
     * 排序字段
     * @var string
     */
    protected $sort_field;

    /**
     * 排序类型
     * @var string
     */
    protected $sort_type;

    /**
     * 查询列表条件模板字符串
     * @var string 例子:Tool::getOptionalQuery(['user_name', 'LIKE'])
     */
    protected $query_list_where_temp;

    /**
     * 构造器
     * 
     * @param array $fields 字段信息
     * @param array $table 生成信息
     */
    public function __construct(array $fields, array $table)
    {
        //基本参数初始化
        $this->root = base_path();
        $this->fields = $fields;
        $this->table = $table;
        $this->class_name = $this->table['className'];
        $this->module_name = $this->table['moduleName'];
        $this->business_name = $this->table['businessName'];
        $this->function_name = $this->table['functionName'];
        //后端生成通用数据初始化
        $this->initBusinessFields();
        $this->initRequiredFields('add_required_fields');
        $this->initRequiredFields('edit_required_fields');
        $this->initImportExportStatus();
        $this->initImgFields();
        $this->buildAddFieldsTemp();
        $this->buildEditFieldsTemp();
        $this->initGenApiType();
        $this->initQueryListDisplayFields();
        $this->initSortInfo();
        $this->initRequiredVerifyFieldsTemp();
        $this->buildQueryWhereContentTemp();
        $this->initIsSortStatus();
        //后端生成所需路径初始化
        $this->initModelGenPath();
        $this->initAdminControllerGenPath();
        $this->initApiControllerGenPath();
    }

    /**
     * 构建查询列表条件模板字符串
     */
    public function buildQueryWhereContentTemp(): void
    {
        $where_content_arr = [];
        foreach ($this->fields as $val) {
            if ($val['isQuery']) {
                $where_content_arr[] = [$val['columnName'], $val['queryType']];
            }
        };
        $this->query_list_where_temp = self::toFormTempStr($where_content_arr, 3);
    }

    /**
     * 初始化排序信息
     */
    private function initSortInfo(): void
    {
        $this->sort_field =  $this->table['options']->SortField ?? "{$this->business_name}_update_time";
        $this->sort_type =  $this->table['options']->SortType ?? 'desc';
    }

    /**
     * 初始化查询列表可显字段
     */
    private function initQueryListDisplayFields(): void
    {
        foreach ($this->fields as $val) {
            if ($val['isList']) {
                $this->query_list_fields[] = $val['columnName'];
            }
        };
    }

    /**
     * 初始化后端模板类型
     */
    private function initGenApiType(): void
    {
        $this->gen_api_type = $this->table['tplCategory'];
    }

    /**
     * 初始化模型层生成所需路径
     */
    private function initModelGenPath(): void
    {
        $this->model_temp_path = self::initFilePath($this->getTempPath('model'));
        $this->model_module_path = self::initFilePath("{$this->root}common/model/{$this->module_name}");
        $this->model_path = self::initFilePath("{$this->model_module_path}/{$this->class_name}.php");
    }

    /**
     * 初始化后台控制器生成所需路径
     */
    private function initAdminControllerGenPath(): void
    {
        $this->admin_con_temp_path = self::initFilePath($this->getTempPath('admin'));
        $this->admin_con_module_path = self::initFilePath("{$this->root}admin/controller/{$this->module_name}");
        $this->admin_con_path = self::initFilePath("{$this->admin_con_module_path}/{$this->class_name}.php");
    }

    /**
     * 初始化前台控制器生成所需路径
     */
    private function initApiControllerGenPath(): void
    {
        $this->api_con_temp_path = self::initFilePath($this->getTempPath('api'));
        $this->api_con_module_path = self::initFilePath("{$this->root}api/controller/{$this->module_name}");
        $this->api_con_path = self::initFilePath("{$this->api_con_module_path}/{$this->class_name}.php");
    }

    /**
     * 获取生成模板文件路径
     * 
     * @param string $type 生成模板文件类型 admin:后台控制器 | api:前台控制器 | model:模型层
     */
    private function getTempPath(string $type): string
    {
        //模板类型
        $temp_type = $this->gen_api_type;
        //若排序处理开启，并且模板类型为crud，则使用crud_sort单表(增删改查+排序处理)
        if ($this->is_sort) {
            $temp_type = ($temp_type == 'crud') ? 'crud_sort' : $temp_type;
        }
        return $this->root . self::TEMP_PATH_CONFIG[$temp_type][$type];
    }

    /**
     * 初始化图片字段变量
     */
    private function initImgFields(): void
    {
        foreach ($this->fields as $val) {
            if ($val['htmlType'] == 'imageUpload') {
                $this->img_fields[] = $val['columnName'];
            }
        }
    }

    /**
     * 初始化导入导出状态
     */
    private function initImportExportStatus(): void
    {
        //其他选项 4：导出 6：导入
        $checked_btn_arr = $this->table['options']->CheckedBtn;
        $this->is_import = in_array('6', $checked_btn_arr);
        $this->is_export = in_array('4', $checked_btn_arr);
    }

    /**
     * 初始化是否排序处理状态
     */
    private function initIsSortStatus(): void
    {
        $this->is_sort = ($this->table['isSort'] == 1);
    }

    /**
     * 构建新增允许字段模板字符
     */
    private function buildAddFieldsTemp(): void
    {
        $field_arr = array_merge(array_keys($this->business_fields), $this->add_required_fields);
        $this->add_fields_temp = self::toFormTempStr($field_arr);
    }

    /**
     * 构建编辑允许字段模板字符
     */
    private function buildEditFieldsTemp(): void
    {
        $field_arr = array_merge(array_keys($this->business_fields), $this->edit_required_fields);
        $this->edit_fields_temp = self::toFormTempStr($field_arr);
    }

    /**
     * 初始化功能必填验证模板字符
     */
    private function initRequiredVerifyFieldsTemp(): void
    {
        $edit_require_fields = [];
        $add_require_fields = [];
        foreach ($this->fields as $val) {
            $column_name = $val['columnName'];
            if ($val['isEdit']) {
                if ($val['isRequired']) {
                    $edit_require_fields[] =  $column_name;
                }
            }
            if ($val['isInsert']) {
                if ($val['isRequired']) {
                    $add_require_fields[] =  $column_name;
                }
            }
        };
        $this->edit_required_verify_temp =  self::toFormTempStr($edit_require_fields, 2);
        $this->add_required_verify_temp = self::toFormTempStr($add_require_fields, 2);
    }

    /**
     * 构建业务字段名
     */
    private function initBusinessFields()
    {
        foreach ($this->fields as $val) {
            if (!$val['isInit']) {
                $this->business_fields[$val['columnName']] = $val['columnComment'];
            }
        }
    }

    /**
     * 生成模块文件夹
     * 
     * @param string $path 模块文件夹路径
     */
    protected function createModuleMkdir(string $module_path): void
    {
        self::mkdir($module_path);
    }

    /**
     * 初始化文件路径
     * 
     * @param string $path 文件路径
     * @return string 初始化后的文件路径
     */
    protected static function initFilePath(string $path): string
    {
        //系统分隔符替换
        return str_replace('/', DIRECTORY_SEPARATOR, $path);
    }

    /**
     * 获取模板文件字符串
     * 
     * @param string $temp_path 模板文件路径
     */
    protected static function getTempStr(string $temp_path): string
    {
        //打开该文件资源(r只读方式打开),读取模板文件内容
        return fread(fopen($temp_path, "r"), filesize($temp_path));
    }

    /**
     * 写入文件
     * 
     * @param string $path 文件路径
     * @param string $content 写入内容
     */
    protected static function writeFile(string $path, string $content): void
    {
        //打开文件资源(w写入方式打开)，进行写入
        fwrite(fopen($path, 'w'), $content);
    }

    /**
     * 初始化必要字段
     * 
     * @param string 必要字段变量名
     * 
     */
    protected function initRequiredFields(string $op_name): void
    {
        $init_data = [];
        foreach ($this->$op_name as $val) {
            $init_data[] = "{$this->business_name}_{$val}";
        }
        $this->$op_name = $init_data;
    }

    /**
     * 创建文件夹
     * 
     * @param string $path 文件夹创建所属路径
     */
    protected static function mkdir(string $path): void
    {
        if (!(new Gen(new \think\App()))->mkdir($path)) {
            throwErrorMsg(__METHOD__ . "创建文件夹失败!");
        }
    }

    /**
     * 数组转换为模板字符串
     * @param array $arr 数组
     * @param int $type 模板字符类型 1:一维数组格式 2:验证器格式 3:列表条件查询 4:关联数组格式 
     */
    protected function toFormTempStr(array $arr, int $type = 1): string
    {
        return (new Gen(new \think\App()))->toFormTempStr($arr, $this->business_fields, $type);
    }
}
