<?php

namespace app\admin\controller\Gen\GenApi\GenModel;

use app\admin\controller\Gen\GenApi\GenApi;
use app\common\exception\Tool;

/**
 * 后端模型层生成类
 */
class Model extends GenApi
{
    /**
     * 生成模型层
     */
    public function createNewModel(): void
    {
        //创建模型层模块目录
        self::createModuleMkdir($this->model_module_path);
        //模板文件字符串替换
        $temp_str = Tool::strReplacePlus(
            self::getTempStr($this->model_temp_path),
            [
                //实体类名
                '{$className}' => $this->class_name,
                //模块名
                '{$moduleName}' => $this->module_name,
                //业务名
                '{$businessName}' => $this->business_name,
                //模型层字段信息
                '{$fields}' => $this->buildFieldsInfoTemp(),
                //模型层导出Excel方法
                '{$exportExcelContent}' =>  $this->buildExportFun(),
                //模型层导入/下载模板Excel表头
                '{$importExcelField}' =>   $this->buildImportDownloadFieldsTemp(),
                //模型层导入Excel方法
                '{$importExcelContent}' => $this->buildImportFunTemp(),
                //模型层导入Excel初始化方法
                '{$importExcelInitContent}' =>  $this->buildImportInitFunTemp(),
                //排序字段
                '{$orderField}' => $this->sort_field,
            ]
        );
        //文件写入
        self::writeFile($this->model_path, $temp_str);
    }

    /**
     * 构建模型层字段信息模板字符串
     */
    public function buildFieldsInfoTemp(): string
    {
        $str = "";
        foreach ($this->fields as $value) {
            $str .=  " '{$value['columnName']}' => '{$value['columnType']}' , \n";
        }
        return $str;
    }

    /**
     * 构建模型层导出方法模板字符串
     */
    private function buildExportFun(): string
    {
        if (!$this->is_export) return '';

        //excel表头字符串构建
        $excel_header = [];
        foreach ($this->business_fields as $name) {
            $excel_header[] = $name;
        };
        $excel_header_temp = $this->toFormTempStr($excel_header);

        //导出数据分配
        $data_str = '';
        foreach ($this->business_fields as $field => $name) {
            //图片字段处理
            if (in_array($field, $this->img_fields)) {
                $data_str .= "Excel::ExportImgFiled(\$val['$field']),\n";
            } else {
                $data_str .= "\$val['{$field}'],\n";
            }
        }
        $data_str = "[\n{$data_str}]";

        //模板字符串构建并返回
        return "
        /**
          * 导出Excel
          * 
          * @param array \$select 导出的数据
          */
        public static function exportExcel(array \$select): void
        {
            \$data = [{$excel_header_temp}];
            foreach (\$select as \$key => \$val) {
                \$data[] = {$data_str};
            }
            \$excel = (new Excel())->exporTsheet(\$data);
            \$excel->save('{$this->function_name}.xlsx');
        }";
    }

    /**
     * 构建导入/下载模板表头模板字符串
     */
    private function buildImportDownloadFieldsTemp(): string
    {
        if (!$this->is_import) return '';

        $init_fields_str = $this->toFormTempStr($this->business_fields, 4);
        $init_fields_str = substr($init_fields_str, 0, strlen($init_fields_str) - 1); //末尾的逗号去除
        return " // excel导入/下载模板表头
        public const EXCELFIELD = {$init_fields_str};";
    }

    /**
     * 构建模型层导入方法模板字符串
     */
    private function buildImportFunTemp(): string
    {
        if (!$this->is_import) return '';

        //模板字符串构建并返回
        return "
        /**
          * 导入excel
          * 
          * @param \app\common\arw\adjfut\src\UploadFile \$file excel
        */
        public static function importExcel(\app\common\arw\adjfut\src\UploadFile \$file): string
        {
            \$msg = [];

            Db::startTrans();
            try {
                \$excel = new Excel(\$file);
                \$data = \$excel->parseExcel(
                    Tool::getExcelRule(self::EXCELFIELD), 
                ['titleLine' => [1]]);
                if (!\$data)  throwErrorMsg('excel无数据', 1);
                \$msg = [];
                foreach (\$data as \$line => \$value) {
                    try {
                        \$model = self::importExcelInit(\$value);
                        \$msg[] = \"{\$line} <span style='color:#27af49'>新增成功!</span><br>\";
                    } catch (\Throwable \$th) {
                        \$msg[] = \"{\$line} <span style='color:red'>{\$th->getMessage()}</span><br>\";
                    }
                }
                Db::commit();
                return implode(', ', \$msg);
            } catch (\Throwable \$th) {
                Db::rollback();
                throw \$th;
            }
        }";
    }

    /**
     * 构建模型层导入初始化方法模板字符串
     */
    private  function buildImportInitFunTemp(): string
    {
        if (!$this->is_import) return '';

        /**
         * (匿名函数)获取excel每行导入数据变量分配-模板字符串
         */
        $getImportAllocationTemp = function () {
            $str = "";
            foreach ($this->business_fields as $field => $name) {
                $str .= "\${$field} = \$value['{$field}'];";
            };
            return $str;
        };
        $import_allocation_temp = $getImportAllocationTemp();

        /**
         * (匿名函数)获取新增的字段值们-模板字符串
         */
        $getAddFieldsTemp = function () {
            $str = "";
            foreach ($this->business_fields as $field => $name) {
                $str .= "'{$field}' => \${$field},\n";
            };
            return $str;
        };
        $add_allocation_temp = $getAddFieldsTemp();

        //模板字符串构建并返回
        return "
        /**
          * 导入excel初始化
          * 
          * @param array \$value excel每行数据
        */
        public static function importExcelInit(array \$value):void
        {
            {$import_allocation_temp}

            self::create(
                [{$add_allocation_temp}],
                {$this->add_fields_temp}
            );
        }
     ";
    }
}
