<?php

namespace Application\Form;

use Application\Common\Enum;
use Application\Common\EventEnum;
use Application\Service\DB\Db;
use Application\Service\DB\Dictionary\Form;
use Application\Service\DB\Dictionary\FormField;
use Application\Service\DB\Dictionary\ItemFormFieldRadio;
use Application\Service\DB\Item\FormFieldRadio;
use Application\Service\Exceptions\InvalidArgumentException;
use Application\Service\Extension\Event;
use Application\Service\Extension\Form\BaseForm;
use Application\Service\Extension\Helper\ArrayHelper;
use Application\Service\Extension\Helper\StringHelper;
use Application\Service\Extension\Helper\ValidatorHelper;
use Application\Service\Extension\Laminas;
use Application\Service\Extension\ValidatorV2\RulesContainer;
use Laminas\Db\Sql\Predicate\Operator;

class FieldForm extends BaseForm
{
    /** 文本模板 */
    const FORM_CONFIG_TEXT = 'TEXT';

    /** 单选模板 */
    const FORM_CONFIG_RADIO = 'RADIO';

    protected string $prefix = 'dictionary';

    private string $rules = '';

    /**
     * 如果当前表单有受试者填写, 只能修改部分字段
     * @var array
     */
    public array $canUpdateField = [];

    /**
     * 如果当前表单有受试者填写, 只能修改部分字段
     * 变量名, 类型, 是否在列表展示, 验证规则, 排序, 名字, 单位
     */
    private const CAN_UPDATE_FIELD = ['checkname_id','checktime_id','form_field_id','var_name', 'type', 'is_list','is_export', 'rules', 'order', 'name', 'unit', 'is_hyperwindow', 'english', 'cut_pre', 'cut_after', 'cut_length', 'cut_start', 'medical_type','default_field_id','default_field_type', 'is_item_form_source', 'item_form_source_set', 'showfiled_name','formchecktime_id','remind_type','default_checktimefield_id','is_hide'];

    /**
     * @param $value
     * @return null
     */
    public function invalidRadioValue($value)
    {
        $request = Laminas::$app->getMvcEvent()->getRequest();

        // 判断 value 值是否在其他单选选项中使用了

        if ($request->getPost('form_type') == FormField::FORM_CONFIG_RADIO && $value == null) {
            throw new InvalidArgumentException("请填写正确的选项值");
        }

        // 没 id 说明是新增, 有 id 是编辑
        $where = $request->getPost('id') ? ['id' => $request->getPost('id')] : ['parent' => $request->getPost('parent')];

        $parent = $this->getFormField()->fetchOne([
            'columns' => ['parent'],
            'where' => $where
        ])['parent'] ?? null;

        if ($parent) {
            // 所有关联的子选项id
            $fieldId = Laminas::$serviceManager->{"{$this->prefix}FormField"}->fetchAll([
                'columns' => ['id'],
                'where' => ['parent' => $parent, 'is_del' => 0]
            ]);

            $data = Laminas::$serviceManager->{"{$this->prefix}FormFieldRadio"}->fetchAll([
                'columns' => ['field_id'],
                'where' => ['field_id' => ArrayHelper::getColumn($fieldId, 'id'), 'value' => intval($value)]
            ]);

            if ($data && (count($data) > 1 || current(ArrayHelper::getColumn($data, 'field_id')) != $request->getPost('id'))) {
                throw new InvalidArgumentException("选项值 {$value} 已存在, 请勿重复添加。");
            }

        }


        return null;
    }

    public function validHyperWindow($value)
    {
        $isAnchorTime = Laminas::$app->getMvcEvent()->getRequest()->getPost('is_anchor');

        if ($isAnchorTime && $value == 1) {
            throw new InvalidArgumentException("超窗判断和基点日期不能同时设置。");
        }

        return null;
    }

    /**
     * 字段名称验证
     * 【新系统】表单内容设置时，类型为“文本（不可编辑）、纯文本”时的变量名、导出以及字段名称可输字符限制的处理--美，蒙
     * https://e.gitee.com/yikeen_project/dashboard?issue=I7TP21
     * @param $value
     * @return null
     */
    public function validName($value)
    {
        $request = Laminas::$app->getMvcEvent()->getRequest();
        if (!in_array($request->getPost('type'), [FormField::FORM_FIELD_TYPE_SPAN, FormField::FORM_FIELD_TYPE_LABEL])) {
            if (mb_strlen($value, '') > 512) {
                throw new InvalidArgumentException("字段名称长度不能大于256字符。");
            }
        }

        return null;
    }

    /**
     * 验证访视日期个数
     */
    public function invalidBookedTime($value)
    {
        $params = Laminas::$app->getMvcEvent()->getRequest();
        if ($value == 1) {

            if ($formType = $this->getForm()->fetchOne(['where' => ['id' => $params->getPost('form_id')]])) {
                if ($formType['type'] == $this->getForm()::FORM_TYPE_MULTI) {
                    throw new InvalidArgumentException("一对多的表单类型不允许设置访视日期, 请将访视日期设置为否。");
                }
            }

            $data = $this->getFormField()->fetchAll(['where' => ['form_id' => $params->getPost('form_id'), 'is_booked_time' => 1]]);

            if ($data && (count($data) > 1 || current(ArrayHelper::getColumn($data, 'id')) != $params->getPost('id'))) {
                throw new InvalidArgumentException(current($data)['name'] . " 已被设置成访视日期 , 请勿重复设置。");
            }
        }

        return null;
    }

    /**
     * 验证 id 是否可以被删除
     */
    public function invalidDeleteId($value)
    {
        $params = Laminas::$app->getMvcEvent()->getRequest();

        /** @var FormFieldRadio $formField */
        $formField = Laminas::$serviceManager->{"{$this->prefix}FormFieldRadio"};

        $query = $formField->fetchOne([
            'where' => [
                'relation_classification' => 2,
                new \Laminas\Db\Sql\Predicate\Expression("FIND_IN_SET('$value',relation_information)")
            ]
        ]);

        // 验证是否已被关联, 被关联不能删除
        if ($query && $this->getFormField()->fetchOne(['where' => ['id' => $query['field_id']]])['is_del'] == 0) {
            throw new InvalidArgumentException("当前选项已被关联。无法删除。");
        }

        $fieldData = $this->getFormField()->fetchOne([
            'where' => ['id' => $value]
        ]);

        // 项目表单验证是否被填写
        if (isset($fieldData['item_id'])) {
            // 验证是已被否填写
            if (Laminas::$serviceManager->patientFormContent->fetchOne(['where' => [
                'item_id' => $fieldData['item_id'],
                'form_id' => $fieldData['form_id'],
                'is_del' => 0
            ]])) {
                throw new InvalidArgumentException("当前表单已有受试者填写。无法进行删除操作。");
            }
        }

        return null;
    }

    /**
     * 验证变量规则, 验证变量名是否重复。
     * @param $val
     * @return null
     */
    public function validVarName($val)
    {

        // 排除掉ocr识别类变量
        $exceptVarName = [
            FormField::FORM_OCR_FIELD_CHECK_IMG,
            FormField::FORM_OCR_FIELD_CHECK_REMARK,
            FormField::FORM_OCR_FIELD_LABORATORY_TEST,
            FormField::FORM_OCR_FIELD_LABORATORY_TEST_FALSE,
            FormField::FORM_OCR_FIELD_LABORATORY_TEST_TRUE,
            FormField::FORM_OCR_FIELD_OUT_PLAN_CHECK,
        ];
        if(in_array($val, $exceptVarName)){
            return null;
        }

        $request = Laminas::$app->getMvcEvent()->getRequest();
        if (($request->getPost('form_type') == FormField::FORM_CONFIG_RADIO && !$val) || ($request->getPost('type') == FormField::FORM_FIELD_TYPE_SPAN)) {
            return null;
        }

        // https://e.gitee.com/yikeen_project/dashboard?issue=I7TP21#note_21368307
        // 纯文本和文本（不可编辑） 这2个类型的。变量名可以不写为空
        if (in_array($request->getPost('type'), [FormField::FORM_FIELD_TYPE_SPAN, FormField::FORM_FIELD_TYPE_LABEL])) {
            if (!$val) {
                return null;
            }
        } else {
            // 标签和纯文本类型不要验证变量名长度和命名规则
            //检查点变量名规则
            $isMatched = preg_match('/^[a-zA-Z_]([a-zA-Z0-9_]+)?$/', $val);

            if (!$isMatched) {
                throw new \Laminas\Validator\Exception\InvalidArgumentException("变量名必须以A-Z（不区分大小写）或下划线（_）开始,且不能包括空格和特殊符号。", 1001);
            }
            if (strlen($val) > 32) {
                throw new InvalidArgumentException("不能超过32个字符", 1001);
            }
        }

        // 验证变量名不能重复
        // 【新系统】变量名，新加不可重复的控制 --李总，白老师
        //https://e.gitee.com/yikeen_project/dashboard?issue=I72KSD
        // 没 id 说明是新增, 有 id 是编辑
        $where = ['item_id' => $request->getPost('item_id'), 'var_name' => $val, 'is_del' => 0];
        $condition = $request->getPost('id') ? [new Operator('id', Operator::OP_NE, $request->getPost('id'))] : null;
        if ($condition !== null) {
            $where = ArrayHelper::merge($where, $condition);
        }

        $data = $this->getFormField()->fetchAll([
            'columns' => ['var_name', 'id', 'name'],
            'where' => $where
        ]);

        // 新增
        if ($request->getPost('id')) {
            if (count($data) > 1) {
                throw new InvalidArgumentException("变量名 `{$val}` 已与 `{$data['name']}` 中的变量名重复, 请勿重复添加。");
            }

            $data = current($data);
            if ($data && $data['id'] != $request->getPost('id')) {
                throw new InvalidArgumentException("变量名 `{$val}` 已与 `{$data['name']}` 中的变量名重复, 请勿重复添加。");
            }
            $c = 1;
        } else {
            $c = 0;
        }

        if ($data && !in_array($val, $exceptVarName) && (count($data) > $c || current(ArrayHelper::getColumn($data, 'var_name')) != $request->getPost('var_name'))) {
            $formName = current($data)['name'];
            throw new InvalidArgumentException("变量名 `{$val}` 已与 `{$formName}` 中的变量名重复, 请勿重复添加。");
        }

        return null;
    }

    /**
     * 创建字典项表单字段
     * @param array $field
     * @return int
     */
    public function createField(array $field = [],$type = 0): int
    {
        Db::beginTransaction();

        $this->initCheckFormField();

        if (!$field) {
            $field = [
                'form_id' => $this->validator->attributes['form_id'],
                'name' => $this->validator->attributes['name'],
                'parent' => $this->validator->attributes['parent'] ?: 0,
                'type' => $this->validator->attributes['type'] ?: 0, // 0 是选项
                'is_list' => $this->validator->attributes['is_list'] ?? 0,
                'is_export' => $this->validator->attributes['is_export'] ?? 1,
                'is_hide' => $this->validator->attributes['is_hide'] ?? 0,
                'dicform_id' => $this->validator->attributes['dicform_id'] ?? 0,
                'order' => $this->validator->attributes['order'] ?: 0,
                'rules' => $this->getRules(),
                'version' => 'v1.0',
                'is_anchor' => $this->validator->attributes['is_anchor'] ?? 0,
                'is_booked_time' => $this->validator->attributes['is_booked_time'] ?? 0,
                'var_name' => $this->validator->attributes['var_name'] ?? '',
                'default' => $this->getDefault() ?: '',
            ];
        }else{
            $field['parent'] = $field['parent'] ?: 0;
            $field['type'] = $field['type'] ?: 0;
            $field['is_list'] = $field['is_list'] ?: 0;
            $field['is_export'] = $field['is_export'] ?: 1;
            $field['is_hide'] = $field['is_hide'] ?: 0;
            $field['dicform_id'] = $field['dicform_id'] ?: 0;
            $field['order'] = $field['order'] ?: 0;
            $field['is_anchor'] = $field['is_anchor'] ?: 0;
            $field['is_booked_time'] = $field['is_booked_time'] ?: 0;
            $field['var_name'] = $field['var_name'] ?: '';

            if($type == 1){
                $this->validator->attributes['form_id']        = $field['form_id'];
                $this->validator->attributes['name']           = $field['name'];
                $this->validator->attributes['parent']         = $field['parent'] ?: 0;
                $this->validator->attributes['type']           = $field['type'] ?: 0; // 0 是选项
                $this->validator->attributes['is_list']        = $field['is_list'] ?: 0;
                $this->validator->attributes['is_export']      = $field['is_export'] ?: 0;
                $this->validator->attributes['is_hide']        = $field['is_hide'] ?: 0;
                $this->validator->attributes['dicform_id']     = $field['dicform_id'] ?: 0;
                $this->validator->attributes['order']          = $field['order'];
                $this->validator->attributes['version']        = $field['version'];
                $this->validator->attributes['is_anchor']      = $field['is_anchor'] ?? 0;
                $this->validator->attributes['is_booked_time'] = $field['is_booked_time'] ?? 0;
                $this->validator->attributes['var_name']       = $field['var_name'];
                $this->validator->attributes['value']          = $field['value'];
                $this->validator->attributes['is_check']       = $field['is_check'];
                $this->validator->attributes['is_score']       = $field['is_score'];
                $this->validator->attributes['score']          = $field['score'];
                $this->validator->attributes['form_type']      = $field['form_type'];

                unset($field['value']);
                unset($field['is_check']);
                unset($field['is_score']);
                unset($field['form_type']);

                //print_r($this->validator->attributes);die;
            }
        }

        // 保存字段数据
        $id = $this->getFormField()->insert($field);

        // 保存关联数据, 不同的类型的值
        $this->_setRelationValue($id);

        // 生成版本表单字段数据
        $this->createVersionField($id);

        //添加/删除表单及表单内容至检查项
        if(isset($field['is_csae'])) {
            $this->getFormField()->saveFormFieldToCheck(['field_id' => $id, 'item_id' => $this->validator->attributes['item_id']]);
        }


        $this->id = $id;
        /** @see Event::initEventMap() */
        Event::trigger(EventEnum::AFTER_EVENT_FORM_FIELD_CREATE, [$this]);

        Db::commit();

        return $id;
    }

    private function getValidatorMinValue()
    {
        $min = $this->validator->attributes['validator']['v-minValue'] ?? '';

        if ($this->validator->attributes['type'] === FormField::FORM_FIELD_TYPE_INTEGER) {
            return $min;
        }

        if ($min !== '') {
            ValidatorHelper::isFloat($min, $this->validator->attributes);
        }

        return $min;
    }

    private function getValidatorMaxValue()
    {
        $max = $this->validator->attributes['validator']['v-maxValue'] ?? '';

        if ($this->validator->attributes['type'] === FormField::FORM_FIELD_TYPE_INTEGER) {
            return $max;
        }

        if ($max !== '') {
            ValidatorHelper::isFloat($max, $this->validator->attributes);
        }

        return $max;
    }

    protected function getDefault()
    {
        $default = $this->validator->attributes['default'] ?? '';

        if (in_array($this->validator->attributes['type'], [FormField::FORM_FIELD_TYPE_INTEGER, FormField::FORM_FIELD_TYPE_TEXT])) {
            return $default;
        }

        if ($default !== '') {
            ValidatorHelper::isFloat($default, $this->validator->attributes);
        }

        return $default;
    }

    private function _setRelationValue($id)
    {
        if ($this->validator->attributes['form_type'] == self::FORM_CONFIG_TEXT) {
            $this->getFormFieldText()->insert([
                'var_name' => $this->validator->attributes['var_name'] ?: '',
                'tips' => $this->validator->attributes['tips'] ?: '',
                'placeholder' => $this->validator->attributes['placeholder'] ?: '',
                'order' => $this->validator->attributes['order'],
                'field_id' => $id,
                'form_id' => $this->validator->attributes['form_id']
            ]);
        } elseif ($this->validator->attributes['form_type'] == self::FORM_CONFIG_RADIO) {
            $fieldId = $this->getFormFieldRadio()->insert([
                'value' => $this->validator->attributes['value'],
                'is_check' => $this->validator->attributes['is_check'] ? 1 : 0,
                'relation_classification' => $this->validator->attributes['relation_classification'],
                'relation_type' => $this->validator->attributes['relation_type'],
                'relation_information' => $this->validator->attributes['relation_information'] ?: 0,
                'field_id' => $id,
                'form_id' => $this->validator->attributes['form_id'],
                'score' => $this->validator->attributes['score'] ?: 0,
                'is_score' => $this->validator->attributes['is_score'] ?: 0,
            ]);

            $this->_setIsFormRelation($fieldId);
        }
    }

    /**
     * 初始化检查项表单
     */
    public function initCheckFormField()
    {
    }

    /**
     * 如果表单被填写了, 只允许修改部分字段
     */
    private function _invalidEdit()
    {
        // 表单原始数据
        // columns 写哪些, 哪些是可以修改的字段
        // 变量名 类型 是否在列表展示 高级验证规则 排序值 都是可修改的
        $selectColumns = self::CAN_UPDATE_FIELD;
        $selectColumns[] = 'is_csae';
        $originData = $this->getFormField()->fetchOne([
            'columns' => $selectColumns,
            'where' => ['id' => $this->validator->attributes['id']]
        ]);

        //判断是否为常规类（识别）【介入报告表单】
        $formData = $this->getForm()->fetchOne(['where'=> [
            'is_del' => 0,
            'id' => $this->validator->attributes['form_id'],
        ],'columns'=>['group_id','var_name','info_collect_type']]);
        $formGroup = !empty($formData) && !empty($formData['group_id']) ? $formData['group_id'] : 0;
        $formCollectCategory = !empty($formData) && !empty($formData['info_collect_type']) ? $formData['info_collect_type'] : 0;
        $new_group_code = Laminas::$serviceManager->dictionaryFormGroup->getOneFieldVal('code',[
            'is_del' => 0,
            'id' => $formGroup,
        ]);
        if(!empty($formGroup) && !empty($formCollectCategory)){
            $new_collectcategory = Laminas::$serviceManager->collectCategory->getOneFieldVal('category_code',[
                'is_del' => 0,
                'id' => $formCollectCategory,
            ]);
            if($new_collectcategory == 'InterventionReport' && $new_group_code == 'GCO' && in_array($formData['var_name'],['JROT','INRB','BAL']) && $this->validator->attributes['var_name'] != '' && $originData['var_name'] != $this->validator->attributes['var_name']){
                if($formData['var_name'] == 'JROT' && in_array($originData['var_name'],['NAME','CASS','XZ','PAMO','TIMI','OTH'])){
                    throw new InvalidArgumentException('【介入报告-病变部位】表单下表单内容【病变部位（NAME）、CASS位置（CASS）、狭窄程度（XZ）、病变形态（PAMO）、TIMI血流（TIMI）、描述（OTH）】的变量名为固定信息，不可再编辑！');
                }
                if($formData['var_name'] == 'INRB' && in_array($originData['var_name'],['ZNAM','DIAM','LEN','POS'])){
                    throw new InvalidArgumentException('【介入报告-支架】表单下表单内容【支架名称（ZNAM）、直径（DIAM）、长度（LEN）、置入部位（POS）】的变量名为固定信息，不可再编辑！');
                }
                if($formData['var_name'] == 'BAL' && in_array($originData['var_name'],['QNAM','QDIA','QLEN','EXS'])){
                    throw new InvalidArgumentException('【介入报告-球囊】表单下表单内容【球囊名称（QNAM）、直径（QDIA）、长度（QLEN）、扩张部位（EXS）】的变量名为固定信息，不可再编辑！');
                }
            }
        }

        // 受试者是否填写过了
        $isPatientWrite = Laminas::$serviceManager->itemForm->getIsPatientWrite($this->validator->attributes['form_id']);

        //常规识别类的表单 当受试者填写过并且当前字段要由隐私改成非隐私 不可以更改
        if(isset($this->validator->attributes['id']) && !empty($this->validator->attributes['id'])){
            if($new_group_code == 'GCO' && $isPatientWrite && !empty($originData['is_hide']) && empty($this->validator->attributes['is_hide'])){
                throw new InvalidArgumentException("当前表单已有受试者填写，无法更改为非隐私字段");
            }
        }

        if ($isPatientWrite && ($originData['is_csae'] == 1 || (isset($this->validator->attributes['is_csae']) && $this->validator->attributes['is_csae'] == 1))) {
            throw new InvalidArgumentException("当前表单已有受试者填写。无法进行编辑操作。");
        }
        unset($originData['is_csae']);

        if ($isPatientWrite) {
            // 目前只能修改文本
            if (in_array($this->validator->attributes['form_type'], [self::FORM_CONFIG_TEXT, self::FORM_CONFIG_RADIO])) {

                foreach ($originData as $originDataKey => $originDataValue) {
                    // 对高级规则做特殊处理
                    if (isset($this->validator->attributes[$originDataKey]) || $originDataKey === 'rules') {
                        if ($originDataKey == 'rules') {
                            $this->validator->attributes[$originDataKey] = $this->getRules();
                        }
                        if ($this->validator->attributes[$originDataKey] != $originDataValue) {
                            $this->canUpdateField = ArrayHelper::merge($this->canUpdateField, [$originDataKey => $this->validator->attributes[$originDataKey]]);
                        }
//                        throw new InvalidArgumentException("当前表单已有受试者填写。只能进行变量名修改。");
                    }
                }
            }
        }

        if ($isPatientWrite && empty($this->canUpdateField)) {
            throw new InvalidArgumentException("当前表单已有受试者填写。无法进行编辑操作。");
        }
    }

    /**
     * 获取可以修改的字段数据
     */
    private function getCanUpdateField(array $canUpdateField = []): array
    {
        if (!$this->canUpdateField) {
            return [];
        }

        $res = [];
        foreach ($canUpdateField as $item) {
            if (isset($this->canUpdateField[$item])) {
                $res[$item] = $this->canUpdateField[$item];
            }
        }

        return $res;
    }

    public function editCheck(){
        $this->_invalidEdit();
    }

    public function editRadioCheck($id){
        $this->_setRelationValue($id);
    }

    public function editField()
    {
        Db::beginTransaction();

        $this->_invalidEdit();

        $this->editFormField();

        if ($this->validator->attributes['form_type'] == self::FORM_CONFIG_TEXT) {
            // 编辑文本表单
            $this->editTextField();
        } elseif ($this->validator->attributes['form_type'] == self::FORM_CONFIG_RADIO) { // 单选表单
            // 编辑单选表单
            $this->editRadioField();
        }

        $this->editVersionField();

        //添加/删除表单及表单内容至检查项
        if(isset($this->validator->attributes['is_csae'])){
            $this->getFormField()->saveFormFieldToCheck(['field_id'=>$this->validator->attributes['id'],'item_id'=>$this->validator->attributes['item_id']]);
        }

        /** @see Event::initEventMap() */
        Event::trigger(EventEnum::AFTER_EVENT_FORM_FIELD_EDIT, [$this]);

        Db::commit();
    }

    private function editFormField()
    {
        // 从未填写过的表单进行编辑, 都有哪些字段可以被编辑
        if (!$this->canUpdateField) {
            $condition = [
                'id' => $this->validator->attributes['id'],
                'name' => $this->validator->attributes['name'],
                'parent' => !StringHelper::isEmpty($this->validator->attributes['parent']) ? $this->validator->attributes['parent'] : 0,
                'order' => !StringHelper::isEmpty($this->validator->attributes['order']) ? $this->validator->attributes['order'] : 1,
                'is_list' => $this->validator->attributes['is_list'] ?: 0,
                'is_export' => $this->validator->attributes['is_export'] ?: 1,
                'type' => $this->validator->attributes['type'] ?: 0,
                'is_anchor' => $this->validator->attributes['is_anchor'] ?: 0,
                'is_booked_time' => $this->validator->attributes['is_booked_time'] ?: 0,
                'var_name' => $this->validator->attributes['var_name'] ?: '',
                'default' => $this->getDefault() ?: '',
                'unit' => $this->validator->attributes['unit'] ?: '',
                'rules' => $this->getRules(),
                'is_hyperwindow' => $this->validator->attributes['is_hyperwindow'] ?: 0,
                'english' => $this->validator->attributes['english'] ?? '',
                'cut_pre' => $this->validator->attributes['cut_pre'] ?? '',
                'cut_after' => $this->validator->attributes['cut_after'] ?? '',
                'cut_length' => $this->validator->attributes['cut_length'] ?? '',
                'cut_start' => $this->validator->attributes['cut_start'] ?? '',
                'is_csae' => $this->validator->attributes['is_csae'] ?? 0,
                'medical_type' => $this->validator->attributes['medical_type'] ?? '',
                'checktime_id' => $this->validator->attributes['checktime_id'] ?? '',
                'checkname_id' => $this->validator->attributes['checkname_id'] ?? '',
                'form_field_id' => $this->validator->attributes['form_field_id'] ?? '',
                'default_field_id' => $this->validator->attributes['default_field_id'] ?? '',
                'default_field_type' => $this->validator->attributes['default_field_type'] ?? '',
                'default_checktimefield_id' => $this->validator->attributes['default_checktimefield_id'] ?? '',
                'is_hide' => $this->validator->attributes['is_hide'] ?: 0,
                'dicform_id' => $this->validator->attributes['dicform_id'] ?: 0,
                'showfiled_name' => $this->validator->attributes['showfiled_name'] ?? '',
                'is_item_form_source' => $this->validator->attributes['is_item_form_source'] ?: 0,
                'item_form_source_set' => $this->validator->attributes['item_form_source_set'] ?? '',
                'formchecktime_id' => $this->validator->attributes['formchecktime_id'] ?? '',
                'remind_type' => $this->validator->attributes['remind_type'] ?? '',
            ];
        } else { // 已经填写过的表单, 有哪些字段可以被编辑
            $condition = ArrayHelper::merge([
                'id' => $this->validator->attributes['id'],
            ], $this->getCanUpdateField(self::CAN_UPDATE_FIELD));
        }

        $this->getFormField()->save($condition);
    }

    /**
     * 构建验证规则
     * @return string
     */
    public function getRules(): string
    {
        if (!$this->validator->attributes['validator']) {
            return '';
        }
        if ($this->rules) {
            return $this->rules;
        }

        $container = new RulesContainer();
        $container->label = isset($this->validator->attributes['name']) ? $this->validator->attributes['name'] : $this->validator->attributes['attr_name'];
        foreach ($this->validator->attributes['validator'] as $validatorName => &$value) {
            if ($value) {
                if ($validatorName == 'v-required') { // 必填
                    $container->rules[] = [
                        'method' => 'required',
                        'attr' => []
                    ];
                } elseif ($validatorName == 'v-maxLength') { // 最大长度
                    $container->rules[] = [
                        'method' => 'string',
                        'attr' => [
                            'max' => $value
                        ]
                    ];
                } elseif ($validatorName == 'v-minLength') { // 最小长度
                    $container->rules[] = [
                        'method' => 'string',
                        'attr' => [
                            'min' => $value
                        ]
                    ];
                } elseif ($validatorName == 'v-minValue') { // 最小值
                    // 处理设置的类型
                    $value = $this->getValidatorMinValue();
                    $container->rules[] = [
                        'method' => 'number',
                        'attr' => [
                            'min' => $value
                        ]
                    ];
                } elseif ($validatorName == 'v-maxValue') { // 最大值
                    $value = $this->getValidatorMaxValue();
                    $container->rules[] = [
                        'method' => 'number',
                        'attr' => [
                            'max' => $value
                        ]
                    ];
                } elseif ($validatorName == 'v-mobile') { // 手机号
                    $container->rules[] = [
                        'method' => 'match',
                        'attr' => [
                            'regex' => '/^1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}$/'
                        ],
                        'message' => '{attribute} 不是一个正确的手机号码.'
                    ];
                } elseif ($validatorName == 'v-email') {
                    $container->rules[] = [
                        'method' => 'match',
                        'attr' => [
                            'regex' => '/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/'
                        ],
                        'message' => '{attribute} 不是一个正确的邮箱.'
                    ];
                } elseif ($validatorName == 'v-uppercase') {
                    $container->rules[] = [
                        'method' => 'uppercase',
                        'attr' => [],
                        'message' => '{attribute} 不是大写字符串.'
                    ];
                } elseif ($validatorName == 'v-textCount') {
                    $container->rules[] = [
                        'method' => 'string',
                        'attr' => [
                            'max' => $value
                        ]
                    ];
                    $container->rules[] = [
                        'method' => 'string',
                        'attr' => [
                            'min' => $value
                        ]
                    ];
                }
            }
        }
        $container->originRules = $this->validator->attributes['validator'];
        $this->rules = serialize($container);

        return $this->rules;
    }

    private function editRadioField()
    {
        // 因为填写过的表单能修改的字段这里都没有, 所以return掉
        if ($this->canUpdateField) {
            return;
        }

        Laminas::$serviceManager->{"{$this->prefix}FormFieldRadio"}->update([
            'value' => $this->validator->attributes['value'],
            'is_check' => $this->validator->attributes['is_check'] ? 1 : 0,
            'relation_classification' => $this->validator->attributes['relation_classification'] ?: 0,
            'relation_type' => $this->validator->attributes['relation_type'] ?: 0,
            'relation_information' => $this->validator->attributes['relation_information'] ?: 0,
            'score' => $this->validator->attributes['score'] ?: 0,
            'is_score' => $this->validator->attributes['is_score'] ?: 0,
        ], ['field_id' => $this->validator->attributes['id']]);

        $this->_setIsFormRelation($this->validator->attributes['id']);
    }

    private function _setIsFormRelation($fieldId)
    {
        // 删除所有关联的表单
        $this->getFormRelation()->update([
            'is_del' => 1,
        ], ['form_id' => $this->validator->attributes['form_id'], 'field_id' => $this->validator->attributes['id']]);

        // 关联表单
        if ($this->validator->attributes['relation_classification'] == ItemFormFieldRadio::RELATION_CLASSIFICATION_FORM) {

            $relationFormId = explode(',', $this->validator->attributes['relation_information']);

            foreach ($relationFormId as $item) {
                $this->getFormRelation()->insert([
                    'form_id' => $this->validator->attributes['form_id'],
                    'field_id' => $fieldId,
                    'relation_form_id' => $item
                ]);
            }
        }
    }

    /**
     * 修改文本字段属性
     */
    private function editTextField()
    {
        if (!$this->canUpdateField) {
            $condition = [
                'tips' => $this->validator->attributes['tips'],
                'order' => $this->validator->attributes['order'],
                'var_name' => $this->validator->attributes['var_name'],
                'placeholder' => $this->validator->attributes['placeholder']
            ];
        } else {
            $condition = ArrayHelper::merge([
                'var_name' => $this->validator->attributes['var_name'],
            ], $this->getCanUpdateField(['var_name']));
        }

        $this->getFormFieldText()->update($condition, ['field_id' => $this->validator->attributes['id']]);
    }

    // 修改排序顺序
    private function orderField(array $field)
    {
        ArrayHelper::multisort($field, 'order');
        return array_column($field, null, 'id');
    }

    /**
     * 返回对应版本的字段内容
     * @return mixed
     */
    private function getFieldVersion()
    {
        return Laminas::$serviceManager->{"{$this->prefix}FormVersion"}->fetchOne([
            'order' => ['id DESC'],
            'where' => [
                'form_id' => $this->validator->attributes['form_id'],
                'version' => 'v1.0',
            ]
        ]);
    }

    /**
     * 重新构建字段
     */
    public function buildVersionField($id = 0, int $formId = 0): string
    {
        $version = 'v1.0';

        if (!$formId) {
            $query = $this->getFormField()->fetchOne([
                'columns' => ['form_id', 'version'],
                'where' => [
                    'id' => $id,
                ]
            ]);

            list($formId, $version) = [$query['form_id'], $query['version']];
        }

        $query = $this->getFormField()->fetchAll([
            'where' => [
                'is_del' => 0,
                'version' => $version,
                'form_id' => $formId
            ]
        ]) ?: [];

        $field = [];
        foreach ($query as $value) {
            // 无父级字段
            if (!$value['parent']) {
                $field[$value['id']]['id'] = $value['id'];
                $field[$value['id']]['name'] = $value['name'];
                $field[$value['id']]['order'] = $value['order'];
                $field[$value['id']]['type'] = $value['type'];
                $field[$value['id']]['is_list'] = $value['is_list'];
                $field[$value['id']]['is_anchor'] = $value['is_anchor'];
                $field[$value['id']]['is_booked_time'] = $value['is_booked_time'];
                $field[$value['id']]['var_name'] = $value['var_name'];
                $field[$value['id']]['default'] = $value['default'];
                $field[$value['id']]['unit'] = $value['unit'];
            } else {
                $field[$value['parent']]['children'][$value['id']] = [
                    'id' => $value['id'],
                    'name' => $value['name'],
                    'order' => $value['order'],
                    'type' => $value['type'],
                    'parent' => $value['parent'],
                ];
            }
        }

        foreach ($field as $key => &$item) {

            // 移除已经添加过的子集
            if (!$item['id']) {
                unset($field[$key]);
            }

            // 处理 form_type
            if (isset($item['children']) || in_array($item['type'], [Enum::FORM_FIELD_TYPE_RADIO, Enum::FORM_FIELD_TYPE_CHECKBOX, Enum::FORM_FIELD_TYPE_DROPDOWN])) {
                $item['form_type'] = self::FORM_CONFIG_TEXT;
                $item['children_form_type'] = self::FORM_CONFIG_RADIO;
                foreach ($item['children'] as &$child) {
                    $childData = $this->getFormField()->getFormData($child['id'], FormField::FORM_CONFIG_RADIO);
                    $child['form_type'] = self::FORM_CONFIG_RADIO;
                    $child['value'] = $childData['value'] ?? 0;
                    $child['is_check'] = $childData['is_check'] ?? 0;
                    $child['score'] = $childData['score'] ?? 0;
                    $child['is_score'] = $childData['is_score'] ?? 0;
                    $child['var_name'] = $childData['var_name'];
                    $child['relation_information'] = $childData['relation_information'] ?: [];
                    $child['relation_classification'] = $childData['relation_classification'] ?: 0;
                    if ($child['relation_information']) {
                        foreach ($child['relation_information'] as $information) {
                            if ($information == 0) {
                                continue;
                            }

                            $field[$information]['parent'][] = $child['id'];
                        }
                    }
                }
                $item['children_list'] = array_keys($item['children']);
            } else {
                $rowData = $this->getFormField()->getFormData($item['id'], FormField::FORM_CONFIG_TEXT);
                $item['placeholder'] = $rowData['placeholder'] ?: '';
                $item['tips'] = $rowData['tips'] ?: '';
                $item['form_type'] = self::FORM_CONFIG_TEXT;
                $item['var_name'] = $rowData['var_name'];
                $item['unit'] = $rowData['unit'];
            }
        }

        // 处理子集排序
        array_walk($field, function (&$item) {
            if (isset($item['children'])) {
                $item['children'] = $this->orderField($item['children']);
            }
        });

        // 处理父集排序
        $field = $this->orderField($field);

        return json_encode($field);
    }

    private function editVersionField()
    {
        $versionField = $this->getFieldVersion();
        $this->saveFormVersion($versionField);
    }

    /**
     * 创建version字段数据
     * @param int $fieldId 表单字段id
     */
    protected function createVersionField(int $fieldId)
    {
        $versionField = $this->getFieldVersion();
        // 新添加表单字段
        // 如果没有添加过version数据, 就给一个默认值存到数据库内
        if (!$versionField) {
            $versionField = [
                'version' => 'v1.0',
                'field' => '[]',
                'form_id' => $this->validator->attributes['form_id'],
            ];
        }

        $this->saveFormVersion($versionField, $fieldId);
    }

    /**
     * @param array $data
     * @param null $id
     */
    private function saveFormVersion(array $data, $id = null)
    {
        // 删除的时候没有form_id
        if (!$this->validator->attributes['form_id']) {
            $this->validator->attributes['form_id'] = $this->getFormField()->fetchOne([
                'where' => ['id' => $this->validator->attributes['id']]
            ])['form_id'];
        }

        $this->getFormVersion()->save(array_merge($data, [
            'field' => $this->getForm()->buildFieldVersion($this->validator->attributes['form_id'])
        ]));

        Laminas::$serviceManager->itemForm->update(['is_field_score' => $this->getForm()::$isFieldScore], ['id' => $this->validator->attributes['form_id']]);
    }


    public function view()
    {
        return $this->getFormField()->getFormData($this->validator->attributes['id'], $this->validator->attributes['form_type']);
    }

    /**
     * 删除表单字段
     */
    public function delete()
    {
        $this->event = EventEnum::EVENT_FORM_FIELD_DELETE;

        $query = Laminas::$serviceManager->{"{$this->prefix}FormField"}->fetchOne([
            'where' => ['id' => $this->validator->attributes['id']]
        ]);

        //删除关联数据Relation
        $ischild = false;
        if(!empty($query['parent'])) $ischild = true;
        $childRadios = $this->getChildRadio($ischild);
        if(!empty($childRadios)) Laminas::$serviceManager->{"{$this->prefix}FormRelation"}->update(['is_del'=>1],['field_id'=>$childRadios]);


        // 删除自身
        $query['is_del'] = 1;
        Laminas::$serviceManager->{"{$this->prefix}FormField"}->save($query);

        // 如果删除的是父级, 所有子集也要删除
        Laminas::$serviceManager->{"{$this->prefix}FormField"}->update(['is_del' => 1], ['parent' => $query['id']]);

       // 重构表单字段数据
        $versionData = Laminas::$serviceManager->{"{$this->prefix}FormVersion"}->fetchOne([
            'where' => [
                'form_id' => $query['form_id'],
                'version' => 'v1.0',
            ]
        ]);
        $this->saveFormVersion($versionData, $this->validator->attributes['id']);

        /** @see Event::initEventMap() */
        Event::trigger(EventEnum::AFTER_EVENT_FORM_FIELD_DELETE, [$this]);

        return $query['name'] ?? '';
    }

    public function getChildRadio(bool $isChild)
    {
        $radioId = [];
        if($isChild){
            $radioId = Laminas::$serviceManager->{"{$this->prefix}FormFieldRadio"}->getOneFieldVal('id',[
                'field_id' => $this->validator->attributes['id']
            ]);
            if(!$radioId) return  [];
            return [$radioId];
        }
        $childFieldId = Laminas::$serviceManager->{"{$this->prefix}FormField"}->fetchCol('id', [
            'parent' => $this->validator->attributes['id'],
            'is_del' => 0,
        ]);
        if(!$childFieldId) return [];
        return Laminas::$serviceManager->{"{$this->prefix}FormFieldRadio"}->fetchCol('id', [
            'field_id' => StringHelper::toArray($childFieldId)
        ]);
    }

    public function getFieldConfig(string $validatorName = 'DictionaryFormField')
    {
        $config = include Laminas::$app->getConfig()['formValidator'][$validatorName];

        // 默认的模板类型
        $default = $this->validator->attributes['form_type'] ?: FieldForm::FORM_CONFIG_TEXT;

        $formType = $this->getForm()->fetchOne(['where' => ['id' => $this->validator->attributes['form_id']]])['type'];

        //规则1: 判断是否是常规识别类的表单 只有常规识别类的表单可设置隐私字段
        $gco_group_id = Laminas::$serviceManager->dictionaryFormGroup->getOneFieldVal('id', 'is_del = 0 and code = "GCO"');
        $form_table  = 'dictionaryForm';
        $radio_table = 'dictionaryFormFieldRadio';
        $formfiled_table = 'dictionaryFormField';
        if ($validatorName == 'ItemFormField') {
            $form_table  = 'itemForm';
            $radio_table = 'itemFormFieldRadio';
            $formfiled_table = 'itemFormField';
        }
        $form_group_id = Laminas::$serviceManager->$form_table->getOneFieldVal('group_id', [
            'id' => $this->validator->attributes['form_id'],
            'is_del' => 0,
        ]);
        //规则7:挂靠字段不能设置隐私字段; 需要判断是否被挂靠 查是否被挂靠 也就是是否被关联
        $relation_information_count = 0;
        if (!empty($this->validator->attributes['id'])) {
            $relation_information_count = Laminas::$serviceManager->$radio_table->getCount([
                'relation_information' => $this->validator->attributes['id'],
            ]);
        }

        if ($gco_group_id <> $form_group_id || $relation_information_count > 0) {
            unset($config[$default]['form']['is_hide']);
        }
        //规则5:常规识别表单针对上传图片/共享图片字段不可设置为隐私字段; 新增页面由前端控制一下
        if (!empty($this->validator->attributes['id'])) {
            $fieldInfo = Laminas::$serviceManager->$formfiled_table->fetchOne([
                'where' => ['id' => $this->validator->attributes['id']]
            ])?? false;
            $fieldType = !empty($fieldInfo) ? $fieldInfo['type'] : 0;
            $fieldvar_name = !empty($fieldInfo) ? $fieldInfo['var_name'] : '';
        }

        if ($gco_group_id == $form_group_id && !empty($this->validator->attributes['id'])) {
            if (
                in_array($fieldType, [
                    FormField::FORM_FIELD_TYPE_UPLOAD_IMAGE,
                    FormField::FORM_FIELD_TYPE_UPLOAD_SHARE_IMAGE,
                ])
            ) {
                unset($config[$default]['form']['is_hide']);
            }
        }

        //随机分组类的表单下的研究分层字段 也就是变量名为系统分配的 需要设置关联字段名称 其余情况都不设置 默认为空
        //echo $this->validator->attributes['var_name'];die;
        $randomgroup_id = Laminas::$serviceManager->dictionaryFormGroup->getOneFieldVal('id', 'is_del = 0 and code = "RDG"');
        if ($randomgroup_id <> $form_group_id || !in_array($fieldvar_name,['RANDOM_GROUP_SYSTEM', 'RANGCA','RANDOM_GROUP_CUSTOM', 'RANGC'])) {
            unset($config[$default]['form']['showfiled_name']);
        }

        // 一对一的不应该显示是否在列表展示选项
        // 现在一对一也要展示???
        if ($formType == Form::FORM_TYPE_SINGLE) {
//            unset($config[$default]['form']['is_list']);
        }

        $config[$default]['form'] = array_values($config[$default]['form'] ?? []);

        return $config[$default];
    }

    protected function getForm()
    {
        return Laminas::$serviceManager->dictionaryForm;
    }

    protected function getFormRelation()
    {
        return Laminas::$serviceManager->dictionaryFormRelation;
    }

    protected function getFormField()
    {
        return Laminas::$serviceManager->dictionaryFormField;
    }

    protected function getFormVersion()
    {
        return Laminas::$serviceManager->dictionaryFormVersion;
    }

    protected function getFormFieldText()
    {
        return Laminas::$serviceManager->dictionaryFormFieldText;
    }

    protected function getFormFieldRadio()
    {
        return Laminas::$serviceManager->dictionaryFormFieldRadio;
    }

}