<?php

declare(strict_types=1);
/**
 * +----------------------------------------------------------------------
 * | ThinkAdmin Plugin for ThinkAdmin
 * +----------------------------------------------------------------------
 * | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
 * +----------------------------------------------------------------------
 * | 官方网站: https://thinkadmin.top
 * +----------------------------------------------------------------------
 * | 开源协议 ( https://mit-license.org )
 * | 免责声明 ( https://thinkadmin.top/disclaimer )
 * | 会员特权 ( https://thinkadmin.top/vip-introduce )
 * +----------------------------------------------------------------------
 * | gitee 代码仓库:https://gitee.com/zoujingli/ThinkAdmin
 * | github 代码仓库:https://github.com/zoujingli/ThinkAdmin
 * +----------------------------------------------------------------------
 */

namespace think\admin;

use think\exception\HttpResponseException;

/**
 * 表单模板构建器
 * 后面会在兼容的基础上慢慢完善.
 * @class Builder
 * @deprecated 试验中建议不使用
 */
class Builder
{
    /**
     * 生成类型.
     * @var string
     */
    private $type;

    /**
     * 显示方式.
     * @var string
     */
    private $mode;

    /**
     * 当前控制器.
     * @var Controller
     */
    private $class;

    /**
     * 提交地址
     * @var string
     */
    private $action;

    /**
     * 表单变量.
     * @var string
     */
    private $variable = '$vo';

    /**
     * 表单项目.
     * @var array
     */
    private $fields = [];

    private $buttons = [];

    /**
     * Constructer.
     * @param string $type 页面类型
     * @param string $mode 页面模式
     */
    public function __construct(string $type, string $mode, Controller $class)
    {
        $this->type = $type;
        $this->mode = $mode;
        $this->class = $class;
    }

    /**
     * 创建表单生成器.
     * @param string $type 页面类型
     * @param string $mode 页面模式
     */
    public static function mk(string $type = 'form', string $mode = 'modal'): Builder
    {
        return Library::$sapp->invokeClass(static::class, ['type' => $type, 'mode' => $mode]);
    }

    /**
     * 设置表单地址
     * @return $this
     */
    public function setAction(string $url): Builder
    {
        $this->action = $url;
        return $this;
    }

    /**
     * 设置变量名称.
     * @return $this
     */
    public function setVariable(string $name): Builder
    {
        $this->variable = $name;
        return $this;
    }

    /**
     * 创建文本输入框架.
     * @param string $name 字段名称
     * @param string $title 字段标题
     * @param string $substr 字段子标题
     * @param array $attrs 附加属性
     * @param mixed $remark
     * @return $this
     */
    public function addTextArea(string $name, string $title, string $substr = '', bool $required = false, $remark = '', array $attrs = []): Builder
    {
        if ($required) {
            $attrs['required'] = 'required';
        }
        $html = "\n\t\t" . '<label class="layui-form-item block relative">';
        $html .= "\n\t\t\t" . sprintf('<span class="help-label %s"><b>%s</b>%s</span>', empty($attrs['required']) ? '' : 'label-required-prev', $title, $substr);
        $html .= "\n\t\t\t" . sprintf('<textarea name="%s" %s placeholder="请输入%s" class="layui-textarea">{%s.%s|default=\'\'}</textarea>', $name, $this->_attrs($attrs), $title, $this->variable, $name);
        if ($remark) {
            $html .= "\n\t\t\t" . sprintf('<span class="help-block">%s</span>', $remark);
        }
        $this->fields[] = "{$html}\n\t\t</lable>";
        return $this;
    }

    /**
     * 创建 Text 输入.
     * @param string $name 字段名称
     * @param string $title 字段标题
     * @param string $substr 字段子标题
     * @param string $remark 字段备注
     * @param bool $required 是否必填
     * @param ?string $pattern 验证规则
     * @param array $attrs 附加属性
     * @return $this
     */
    public function addTextInput(string $name, string $title, string $substr = '', bool $required = false, string $remark = '', ?string $pattern = null, array $attrs = []): Builder
    {
        $attrs['vali-name'] = $title;
        if ($required) {
            $attrs['required'] = 'required';
        }
        if (is_string($pattern)) {
            $attrs['pattern'] = $pattern;
        }
        return $this->addInput($name, $title, $substr, $remark, $attrs);
    }

    /**
     * 创建密钥输入框.
     * @param string $name 字段名称
     * @param string $title 字段标题
     * @param string $substr 字段子标题
     * @param string $remark 字段备注
     * @param bool $required 是否必填
     * @param ?string $pattern 验证规则
     * @param array $attrs 附加属性
     * @return $this
     */
    public function addPassInput(string $name, string $title, string $substr = '', bool $required = false, string $remark = '', ?string $pattern = null, array $attrs = []): Builder
    {
        $attrs['type'] = 'password';
        return $this->addTextInput($name, $title, $substr, $required, $remark, $pattern, $attrs);
    }

    /**
     * 添加取消按钮.
     * @param string $name 按钮名称
     * @param string $confirm 确认提示
     * @return $this
     */
    public function addCancelButton(string $name = '取消编辑', string $confirm = '确定要取消编辑吗?'): Builder
    {
        return $this->addButton($name, $confirm, 'button', 'layui-btn-danger', ['data-close' => null]);
    }

    /**
     * 添加提交按钮.
     * @param string $name 按钮名称
     * @param string $confirm 确认提示
     * @return $this
     */
    public function addSubmitButton(string $name = '保存数据', string $confirm = ''): Builder
    {
        return $this->addButton($name, $confirm, 'submit');
    }

    /**
     * 添加上传单图字段.
     * @param string $name 字段名称
     * @param string $title 字段标题
     * @param string $substr 字段子标题
     * @param bool $required 必填字段
     * @param array $attrs 附加属性
     * @return $this
     */
    public function addUploadOneImage(string $name, string $title, string $substr = '', bool $required = false, array $attrs = []): Builder
    {
        if ($required) {
            $attrs['required'] = 'required';
        }
        return $this->_addUploadOneView($name, $title, $substr, $attrs);
    }

    /**
     * 添加上传视频字段.
     * @param string $name 字段名称
     * @param string $title 字段标题
     * @param string $substr 字段子标题
     * @param bool $required 必填字段
     * @param array $attrs 附加属性
     * @return $this
     */
    public function addUploadOneVideo(string $name, string $title, string $substr = '', bool $required = false, array $attrs = []): Builder
    {
        if ($required) {
            $attrs['required'] = 'required';
        }
        return $this->_addUploadOneView($name, $title, $substr, $attrs, 'video');
    }

    /**
     * 创建上传多图字段.
     * @param string $name 字段名称
     * @param string $title 字段标题
     * @param string $substr 字段子标题
     * @param bool $required 必填字段
     * @param array $attrs 附加属性
     * @return $this
     */
    public function addUploadMulImage(string $name, string $title, string $substr = '', bool $required = false, array $attrs = []): Builder
    {
        if ($required) {
            $attrs['required'] = 'required';
        }
        $attrs = array_merge($attrs, ['type' => 'hidden', 'placeholder' => "请上传{$title} ( 多图 )"]);
        $html = "\n\t\t" . '<div class="layui-form-item">';
        $html .= "\n\t\t\t" . sprintf('<span class="help-label %s"><b>%s</b>%s</span>', empty($attrs['required']) ? '' : 'label-required-prev ', $title, $substr);
        $html .= "\n\t\t\t" . '<div class="layui-textarea help-images layui-bg-gray">';
        $html .= "\n\t\t\t\t" . sprintf('<input name="%s" %s value="{%s.%s|default=\'\'}">', $name, $this->_attrs($attrs), $this->variable, $name);
        $html .= "\n\t\t\t" . '</div>' . "\n\t\t" . '</div>';
        $html .= "\n\t\t" . sprintf('<script>$("input[name=%s]").uploadMultipleImage()</script>', $name);
        $this->fields[] = $html;
        return $this;
    }

    /**
     * 创建复选框字段.
     * @param string $name 字段名称
     * @param string $title 字段标题
     * @param string $substr 字段子标题
     * @param string $vname 变量名称
     * @param bool $required 是否必选
     * @param array $attrs 附加属性
     * @return $this
     */
    public function addCheckInput(string $name, string $title, string $substr, string $vname, bool $required = false, array $attrs = [], string $type = 'checkbox'): Builder
    {
        if ($required) {
            $attrs['required'] = 'required';
        }
        $attrs = array_merge($attrs, ['type' => $type, 'lay-ignore' => null, 'name' => $name . ($type === 'checkbox' ? '[]' : '')]);
        $html = "\n\t\t" . '<div class="layui-form-item">';
        $html .= "\n\t\t\t" . sprintf('<span class="help-label %s"><b>%s</b>%s</span>', empty($attrs['required']) ? '' : ' label-required-prev', $title, $substr);
        $html .= "\n\t\t\t" . '<div class="layui-textarea help-checks layui-bg-gray">';
        $html .= "\n\t\t\t\t" . sprintf('<!--{foreach $%s as $k=>$v}item-->', $vname);
        $html .= "\n\t\t\t\t" . sprintf('<label class="think-%s label-required-null">', $type);
        $html .= "\n\t\t\t\t\t" . sprintf('<!--if{if isset(%s.types) and is_array(%s.types) and in_array($k,%s.types)}-->', $this->variable, $this->variable, $this->variable);
        $html .= "\n\t\t\t\t\t" . sprintf('<input value="{$k|default=\'\'}" %s checked> {$v|default=\'\'}', $this->_attrs($attrs));
        $html .= "\n\t\t\t\t\t" . '<!--{else}else-->';
        $html .= "\n\t\t\t\t\t" . sprintf('<input value="{$k|default=\'\'}" %s> {$v|default=\'\'}', $this->_attrs($attrs)) . "\n";
        $html .= "\n\t\t\t\t\t" . '<!--{/if}if-->';
        $html .= "\n\t\t\t\t" . '</label>';
        $html .= "\n\t\t\t\t" . '<!--{/foreach}end-->';
        $this->fields[] = $html . "\n\t\t\t</div>\n\t\t</div>";
        return $this;
    }

    /**
     * 添加单选框架字段.
     * @param string $name 字段名称
     * @param string $title 字段标题
     * @param string $substr 字段子标题
     * @param string $vname 变量名称
     * @param bool $required 是否必选
     * @param array $attrs 附加属性
     * @return $this
     */
    public function addRadioInput(string $name, string $title, string $substr, string $vname, bool $required = false, array $attrs = []): Builder
    {
        return $this->addCheckInput($name, $title, $substr, $vname, $required, $attrs, 'radio');
    }

    /**
     * 显示模板内容.
     * @return mixed
     */
    public function fetch(array $vars = [])
    {
        $html = '';
        $type = "{$this->type}.{$this->mode}";
        if ($type === 'form.page') {
            $html = $this->_buildFormPage();
        } elseif ($type === 'form.modal') {
            $html = $this->_buildFormModal();
        }
        foreach ($this->class as $k => $v) {
            $vars[$k] = $v;
        }
        throw new HttpResponseException(display($html, $vars));
    }

    /**
     * 增加输入表单元素.
     * @param string $name 字段名称
     * @param string $title 字段标题
     * @param string $subtitle 字段子标题
     * @param string $remark 字段备注
     * @param array $attrs 附加属性
     * @return $this
     */
    protected function addInput(string $name, string $title, string $subtitle = '', string $remark = '', array $attrs = []): Builder
    {
        $html = "\n\t\t" . '<label class="layui-form-item block relative">';
        $html .= "\n\t\t\t" . sprintf('<span class="help-label %s"><b>%s</b>%s</span>', empty($attrs['required']) ? '' : 'label-required-prev', $title, $subtitle);
        $html .= "\n\t\t\t" . sprintf('<input name="%s" %s placeholder="请输入%s" value="{%s.%s|default=\'\'}" class="layui-input">', $name, $this->_attrs($attrs), $title, $this->variable, $name);
        if ($remark) {
            $html .= "\n\t\t\t" . sprintf('<span class="help-block">%s</span>', $remark);
        }
        $this->fields[] = "{$html}\n\t\t</label>";
        return $this;
    }

    /**
     * 字段属性转换.
     */
    protected function _attrs(array $attrs, string $html = ''): string
    {
        foreach ($attrs as $k => $v) {
            $html .= is_null($v) ? sprintf(' %s', $k) : sprintf(' %s="%s"', $k, $v);
        }
        return $html;
    }

    /**
     * 添加表单按钮.
     * @param string $name 按钮名称
     * @param string $confirm 确认提示
     * @param string $type 按钮类型
     * @param string $class 按钮样式
     * @param array $attrs 附加属性
     * @return $this
     */
    protected function addButton(string $name, string $confirm, string $type, string $class = '', array $attrs = []): Builder
    {
        $attrs['type'] = $type;
        if ($confirm) {
            $attrs['data-confirm'] = $confirm;
        }
        $this->buttons[] = sprintf('<button class="layui-btn %s" %s>%s</button>', $class, $this->_attrs($attrs), $name);
        return $this;
    }

    /**
     * 添加上传单个文件.
     * @param string $name 字段名称
     * @param string $title 字段标题
     * @param string $substr 字段子标题
     * @param array $attrs 附加属性
     * @param string $type 上传类型
     * @return $this
     */
    private function _addUploadOneView(string $name, string $title, string $substr = '', array $attrs = [], string $type = 'image'): Builder
    {
        $attrs = array_merge($attrs, ['type' => 'text', 'placeholder' => "请上传{$title}", 'vali-name' => $title]);
        $html = "\n\t\t" . '<div class="layui-form-item">';
        $html .= "\n\t\t\t" . sprintf('<span class="help-label %s"><b>%s</b>%s</span>', empty($attrs['required']) ? '' : 'label-required-prev', $title, $substr);
        $html .= "\n\t\t\t" . '<div class="relative block label-required-null">';
        $html .= "\n\t\t\t\t" . sprintf('<input class="layui-input layui-bg-gray" name="%s" %s value="{%s.%s|default=\'\'}">', $name, $this->_attrs($attrs), $this->variable, $name);
        if ($type === 'image') {
            $html .= "\n\t\t\t\t" . sprintf('<a class="layui-icon layui-icon-upload input-right-icon" data-file="image" data-field="%s" data-type="gif,png,jpg,jpeg"></a>', $name);
        } else {
            $html .= "\n\t\t\t\t" . sprintf('<a class="layui-icon layui-icon-upload input-right-icon" data-file data-field="%s" data-type="mp4"></a>', $name);
        }
        $html .= "\n\t\t\t</div>\n\t\t</div>";
        if ($type === 'image') {
            $html .= "\n\t\t" . sprintf('<script>$("input[name=%s]").uploadOneImage()</script>', $name);
        } else {
            $html .= "\n\t\t" . sprintf('<script>$("input[name=%s]").uploadOneVideo()</script>', $name);
        }
        $this->fields[] = $html;
        return $this;
    }

    /**
     * 生成弹层表单模板
     */
    private function _buildFormModal(): string
    {
        $html = sprintf('<form action="%s" method="post" data-auto="true" class="layui-form layui-card">', $this->action ?? url()->build());
        $html .= "\n\t" . '<div class="layui-card-body padding-left-40">' . join("\n", $this->fields);
        if (count($this->buttons)) {
            $html .= "\n\n\t\t" . '<div class="hr-line-dashed"></div>';
            $html .= "\n\t\t" . sprintf('{notempty name="vo.id"}<input type="hidden" value="{%s.id}" name="id">{/notempty}', $this->variable);
            $html .= "\n\t\t" . sprintf('<div class="layui-form-item text-center">%s</div>', "\n\t\t\t" . join("\n\t\t\t", $this->buttons) . "\n\t\t");
            $html .= "\n\t" . '</div>';
        }
        return $html . "\n</form>";
    }

    /**
     * 生成页面表单模板
     */
    private function _buildFormPage(): string
    {
        return '';
    }
}