<?php

namespace Application\Service\Extension\FormPreview;

use Application\Common\DictionaryVarNameEnum;
use Application\Common\Enum;
use Application\Service\DB\Dictionary\Form;
use Application\Service\DB\Dictionary\FormField;
use Application\Service\Extension\Helper\ArrayHelper;
use Application\Service\Extension\Helper\SDMHelper;
use Application\Service\Extension\Laminas;

class BaseForm
{
    protected string $previewScenario = 'default';

    protected ?int $formId = null;

    /**
     * 生成出来的字段
     * @var array
     */
    protected array $generateFields = [];

    public function getConfig()
    {
        $config = $this->generateFields = [];
    }


    private function _handleMultiType(int $formId, bool $debugMode = false)
    {
        $map = $form = $table = [];
        $versionData = SDMHelper::app()->form->getVersionData($this->formId);
        foreach ($versionData as $versionKey => $versionDatum) {
            if (!isset($versionDatum['parent'])) {
                $form[$versionKey] = $this->_buildConfigV2($versionDatum, $versionKey);

                $map = ArrayHelper::merge($map, $this->handleMatchConfig($versionDatum, $versionKey, $versionData));
            }
        }


        // 一对多表格第一个表头要加上宽度
        $index = 0;
        // 哪些是表格上展示的字段
        foreach ($versionData as $versionDatum) {
            if ($versionDatum['is_list'] == 1) {
                $table[$versionDatum['id']] = [
                    'label' => $form[$versionDatum['id']]['label'] ?? $versionDatum['name'],
                    'prop' => $form[$versionDatum['id']]['prop'] ?? $versionDatum['id'],
                ];

                // 一对多表格第一个表头要加上宽度
                if ($index == 0) {
                    $table[$versionDatum['id']]['width'] = '200';
                }
            }
            $index++;
        }

        // 表格上展示的字段追加分值列
        if ((bool)Laminas::$serviceManager->itemFormFieldRadio->memoryCache()->fetchOne([
            'columns' => ['id'], 'where' => ['is_score' => 1, 'form_id' => $this->formData['id']]
        ])) {
            $table['score'] = [
                'label' => "分值", //"分值(合计: {$this->getTotalScore()})",
                'prop' => 'score',
            ];
        }

        $table = array_values($table);

        // 如果只有一个表头, 就去掉宽度
        if (count($table) == 1) {
            unset($table[0]['width']);
        }

        return ArrayHelper::merge(['form' => array_values($form), 'table' => array_values($table)], $map);
    }

    /**
     * 预留的钩子
     * @param array $row
     * @return array
     */
    protected function beforeBuild(array $row): array
    {
        return $row;
    }

    private function afterBuild($res)
    {
        // 表单计算公式
        if ($this->formExpression && isset($res['var_name']) &&$res['var_name'] === $this->formExpression['result']) {
            $h = function ($expression) {
                $fields = Laminas::$serviceManager->itemFormField->fetchAll([
                    'where' => ['form_id' => $this->formData['id'], 'parent' => 0]
                ]);

                $allVarName = implode('|', ArrayHelper::getColumn($fields, 'var_name'));
                $pregStr = "($allVarName)";

                $ex = $expression[0];
                // 兼容旧版本公式
                if (count($expression) > 1) {
                    $ex = implode($this->formExpression['expression']);
                }
                preg_match_all("/\b{$pregStr}\b/", $ex, $matches);
                return array_values(array_unique(array_filter($matches[0])));
            };

            $res['expression'] = $h($this->formExpression['expression']);
        }

        // 共享识别类表单, 除了上传图片这个字段都需要禁止掉
        if ($this->previewScenario != self::SCENARIO_SHARE_FORM_UNLOCK && $this->formData['group_id'] == FormGroup::NORMAL_OCR && $res['type'] != 'UploadImg') {
            $res['disabled'] = true;
        }

        if ($this->previewScenario === self::SCENARIO_CM_LIST_VIEW) {
            if ($res['var_name'] !== DictionaryVarNameEnum::COLLECT_MEDICAL_TAKE_CMINDC) {
                $res['disabled'] = true;
            } else {
                $res['is_select_change'] = true;
            }
        }

        $this->setNote($res);
        // 为类型为 `文本` 加上默认值
        return $res;
    }

    private function _buildConfigV2(array $row, $prop = null)
    {
        $row = $this->beforeBuild($row);

        $originType = $row['type'];

        if (
            in_array($row['type'], [
                FormField::FORM_FIELD_TYPE_DATE_UK,
                FormField::FORM_FIELD_TYPE_TEXT,
                FormField::FORM_FIELD_TYPE_TEXTAREA,
                FormField::FORM_FIELD_TYPE_DATE,
                FormField::FORM_FIELD_TYPE_DATE_SECOND,
                FormField::FORM_FIELD_TYPE_DATETIME,
                FormField::FORM_FIELD_TYPE_INTEGER,
                FormField::FORM_FIELD_TYPE_FLOAT_1,
                FormField::FORM_FIELD_TYPE_FLOAT_2,
                FormField::FORM_FIELD_TYPE_FLOAT_3,
                FormField::FORM_FIELD_TYPE_LABEL,
                FormField::FORM_FIELD_TYPE_SPAN,
            ])
        ) {
            $res = [
                'type' => $this->_getType($row['type']),
                'label' => $row['type'] == FormField::FORM_FIELD_TYPE_SPAN ? '' : $row['name'],
                'placeholder' => $this->getPlaceholder($row),
                'tips' => $this->getTips($row),
                'prop' => strval($prop ?: $row['id']),
                'rules' => $this->getRules($row),
                'var_name' => $row['var_name'],
            ];

            // 返回默认值
            if (
                in_array($row['type'], [
                    FormField::FORM_FIELD_TYPE_TEXT,
                    FormField::FORM_FIELD_TYPE_INTEGER,
                    FormField::FORM_FIELD_TYPE_FLOAT_1,
                    FormField::FORM_FIELD_TYPE_FLOAT_2,
                    FormField::FORM_FIELD_TYPE_FLOAT_3,
                    FormField::FORM_FIELD_TYPE_DATE,
                    FormField::FORM_FIELD_TYPE_DATE_UK,
                    FormField::FORM_FIELD_TYPE_DATE_SECOND,
                    FormField::FORM_FIELD_TYPE_DATETIME,
                    FormField::FORM_FIELD_TYPE_LABEL,
                    FormField::FORM_FIELD_TYPE_SPAN,
                ]) && isset($row['default'])
            ) {
                $res['default'] = in_array($row['type'], [FormField::FORM_FIELD_TYPE_LABEL, FormField::FORM_FIELD_TYPE_SPAN]) ? $this->getPlaceholder($row) : $row['default'];
            }

            // 返回单位
            if (
                in_array($row['type'], [
                    FormField::FORM_FIELD_TYPE_TEXT,
                    FormField::FORM_FIELD_TYPE_INTEGER,
                    FormField::FORM_FIELD_TYPE_FLOAT_1,
                    FormField::FORM_FIELD_TYPE_FLOAT_2,
                    FormField::FORM_FIELD_TYPE_FLOAT_3
                ]) && isset($row['unit'])
            ) {
                $res['unit'] = $row['unit'];
            }
            // label 标签
            if ($row['type'] == FormField::FORM_FIELD_TYPE_LABEL) {
                $res['disabled'] = true;
            }

        } elseif (in_array($row['type'], [Enum::FORM_FIELD_TYPE_RADIO, Enum::FORM_FIELD_TYPE_CHECKBOX, FormField::FORM_FIELD_TYPE_DROPDOWN])) {
            $config = [
                'type' => $this->_getType($row['type']),
                'label' => $row['name'],
                'prop' => strval($prop ?: $row['id']),
                'rules' => $this->getRules($row),
                'var_name' => $row['var_name'],
                'random' => $row['random'] ?? ''
            ];

            if ($default = $this->_getDefault($row)) {
                $config['default'] = $default;
            }

            if ($child = $this->_getChild($row)) {
                $config[$child[0]] = $child[1];
            }

            $res = $config;
        } elseif (in_array($row['type'], [Enum::FORM_FIELD_TYPE_UPLOAD_IMAGE, FormField::FORM_FIELD_TYPE_UPLOAD_SHARE_IMAGE])) {
            $res = [
                'type' => $this->_getType($row['type']),
                'label' => $row['name'],
                'tips' => $this->getTips($row),
                'prop' => strval($prop ?: $row['id']),
                'imageUrl' => '',
                'fileListImg' => [],
                'action' => \Application\Controller\CommonController::UPLOAD_IMG_URL,
                'var_name' => $row['var_name'],
                'rules' => $this->getRules($row),
            ];

            // 识别类表单在图文识别的地方不要展示图片的字段
            if ($this->previewScenario === self::SCENARIO_SHARE_FORM_UNLOCK && $row['type'] == FormField::FORM_FIELD_TYPE_UPLOAD_SHARE_IMAGE) {
                $res = [];
            } elseif ($this->formData['type'] == Form::FORM_TYPE_MULTI && $this->previewScenario == 'default' && $row['type'] == FormField::FORM_FIELD_TYPE_UPLOAD_SHARE_IMAGE) {
                $res = [];
            }
        } elseif ($row['type'] == Enum::FORM_FIELD_TYPE_UPLOAD_FILE) {
            $res = [
                'type' => $this->_getType($row['type']),
                'label' => $row['name'],
                'tips' => $this->getTips($row),
                'prop' => strval($prop ?: $row['id']),
                'fileList' => [],
                'action' => \Application\Controller\CommonController::UPLOAD_URL,
                'var_name' => $row['var_name'],
                'rules' => $this->getRules($row),
            ];
        } elseif ($row['type'] == Enum::FORM_FIELD_TYPE_EDITOR) {
            $res = [
                'type' => $this->_getType($row['type']),
                'label' => $row['name'],
                'prop' => strval($prop ?: $row['id']),
                'var_name' => $row['var_name'],
            ];
        } elseif (is_string($row['type'])) { // 如果是文本类型的, 就返回自身 (手写签名)
            $res = [
                'type' => $row['type'],
                'label' => $row['name'],
                'prop' => $row['prop'] ?? '',
            ];
        }

        // 处理正则表达式
        if ($regex = $this->getRegex($originType)) {
            $res['regex'] = $regex;
        }

        if (is_string($row['id']) && isset($row['is_report_special'])) {
            $res['is_report_special'] = $row['is_report_special'];
        }

        return $this->afterBuild($res);
    }

    private function _getChild(array $row)
    {
//        $request = Laminas::$app->getMvcEvent() !== null ? Laminas::$app->getMvcEvent()->getRequest() : null;
        $options = [];
        if (!isset($row['children'])) {
            if (in_array($row['var_name'], ['RANDOM_GROUP_CUSTOM', 'RANGC'])) { // 手写随机分组
                $row['children'] = Laminas::$serviceManager->itemRandom->fetchAll([
                    'columns' => ['random_name as name', 'id as value'],
                    'where' => ['is_del' => 0, 'item_id' => $this->getRequestParams('item_id'), 'type' => 2]
                ]) ?: [];

                foreach ($row['children'] as $k => $item) {
                    $relationFieldId = $item['value'];
                    $row['children'][$k] = ['name' => $item['name'], 'value' => $item['value']];
                    $row['children'][$k]['relation_information'][] = $relationFieldId;
                    $this->_attachField[$row['id']] = $row;
                    $this->_attachFieldVersion[$relationFieldId] = [
                        "id" => $relationFieldId,
                        "name" => "随机号",
                        "order" => "10",
                        "type" => "1",
                        "is_list" => "0",
                        "is_anchor" => "0",
                        "is_booked_time" => "0",
                        "placeholder" => "请输入随机号",
                        "tips" => "请输入随机号",
                        "form_type" => "TEXT",
                        "code" => "随机号",
                        'var_name' => 'RANDOM_GROUP_CUSTOM_CONTENT'
                    ];
                }
            } elseif (in_array($row['var_name'], ['RANDOM_GROUP_SYSTEM', 'RANGCA'])) { // 系统分配随机分组
                if ($this->getRequestParams('item_id') && $this->getRequestParams('itemsig_id') && $this->getRequestParams('patient_id')) {
                    $row['children'] = Laminas::$serviceManager->itemRandomdetails->getRandomdetailsNumberPop(
                        $this->getRequestParams('item_id'),
                        $this->getRequestParams('itemsig_id'),
                        $this->getRequestParams('patient_id')
                    );
                }

                foreach ($row['children'] ?: [] as $k => $item) {
                    $relationFieldId = $item['id'];
                    $row['children'][$k] = ['name' => $item['group_name'], 'value' => $item['id']];
                    $row['children'][$k]['relation_information'][] = $relationFieldId;
                    $row['children'][$k]['var_name'] = '';
                    $row['children'][$k]['is_score'] = '';
                    $this->_attachField[$row['id']] = $row;
                    $this->_attachFieldVersion[$relationFieldId] = [
                        "id" => $relationFieldId,
                        "name" => "随机号/方案分组",
                        "order" => "10",
                        "type" => "12",
                        "is_list" => "0",
                        "is_anchor" => "0",
                        "is_booked_time" => "0",
                        "placeholder" => "请输入随机号/方案分组",
                        "tips" => "请输入随机号/方案分组",
                        "form_type" => "TEXT",
                        "code" => "随机号/方案分组",
                        'children' => [
                            [
                                'name' => $this->getMedicalName($item),
                                'value' => $item['rand_number']['id'],
                                'is_score' => 0,
                                'var_name' => ''
                            ]
                        ],
                        'var_name' => 'RANDOM_GROUP_SYSTEM_CONTENT',
                        'random' => $item
                    ];
                }
            } elseif ($row['var_name'] == DictionaryVarNameEnum::COLLECT_MEDICAL_TAKE_CMINDC) { // 用药原因【获取字典项设置信息】
                $row['children'] = Laminas::$serviceManager->collectMedicaltake->fetchAll([
                    'columns' => ['id', 'name', 'english'],
                    'order' => ['take_order'],
                    'where' => [
                        'is_del' => 0,
                        'take_type' => 6
                    ]
                ]);
                if ($this->previewScenario == self::SCENARIO_CM_LIST_VIEW) {
                    $row['children'][] = ['id' => '2', 'name' => '属于已有AE', 'english' => ''];
                    $row['children'][] = ['id' => '1', 'name' => '属于新增AE', 'english' => ''];
                }

                foreach ($row['children'] ?: [] as $k => $item) {
                    $row['children'][$k] = ['name' => $item['name'], 'value' => $item['id']];
                    $row['children'][$k]['var_name'] = $item['english'];
                    $row['children'][$k]['is_score'] .= '';
                    $row['children'][$k]['id'] = $item['id'];
                }

                $this->_attachField[88888] = [
                    'name' => 'xxx',
                    'type' => FormField::FORM_FIELD_TYPE_TEXT
                ];
                $this->_attachFieldVersion[88888] = [
                    "id" => 88888,
                    "name" => "随机号",
                    "order" => "10",
                    "type" => "1",
                    "is_list" => "0",
                    "is_anchor" => "0",
                    "is_booked_time" => "0",
                    "placeholder" => "请输入随机号",
                    "tips" => "请输入随机号",
                    "form_type" => "TEXT",
                    "code" => "随机号",
                    'var_name' => 'RANDOM_GROUP_CUSTOM_CONTENT'
                ];
            }
        }

        $index = 0;
        foreach ($row['children'] ?? [] as $item) {
            // 必须要有label
            if (!$item['name']) {
                continue;
            }

            if (isset($item['is_score']) && $item['is_score'] == 1) {
                $options[$index] = [
                    'label' => $item['name'],
                    'value' => $item['value'],
                    'score' => floatval($item['score']), // 兼容非整数分值
                    'is_score' => true,
                    'id' => intval($item['id']),
                    'var_name' => $item['id']
                ];
            } else {
                $options[$index] = ['label' => $item['name'], 'value' => $item['value'],  'is_score' => false, 'score' => 0, 'id' => intval($item['id']), 'var_name' => $item['id']];
            }

            // 不检查需要提示一下
            // 【新系统】不检查时，提示：请填写备注说明。（注：只是提示而已，不做实际控制性功能，不填时表单也可正常提交）--美
            // https://e.gitee.com/yikeen_project/issues/table?issue=I6MYDV
            if (isset($item['var_name']) && $item['var_name'] == 'NC') {
                $options[$index]['is_dialog'] = true;
            }

            $index++;
        }

        return [$this->_getChildKey($row['type']), $options];
    }

    /**
     * @param string $type
     * @return string
     * @throws \Exception
     */
    private function _getType(string $type): string
    {
        switch ($type) {
            case Enum::FORM_FIELD_TYPE_INTEGER:
            case Enum::FORM_FIELD_TYPE_FLOAT_1:
            case Enum::FORM_FIELD_TYPE_FLOAT_2:
            case Enum::FORM_FIELD_TYPE_FLOAT_3:
            case Enum::FORM_FIELD_TYPE_TEXT:
                return 'Input';
            case Enum::FORM_FIELD_TYPE_DATE_UK:
                return 'Uk';
            case FormField::FORM_FIELD_TYPE_DATE_SECOND:
                return 'DateTimeSecond';
            case Enum::FORM_FIELD_TYPE_DATE:
                return 'Date';
            case Enum::FORM_FIELD_TYPE_DATETIME:
                return 'DateTime';
            case Enum::FORM_FIELD_TYPE_RADIO:
                return 'Radio';
            case Enum::FORM_FIELD_TYPE_CHECKBOX:
                return 'Checkbox';
            case Enum::FORM_FIELD_TYPE_UPLOAD_IMAGE:
            case FormField::FORM_FIELD_TYPE_UPLOAD_SHARE_IMAGE:
                return 'UploadImg';
            case Enum::FORM_FIELD_TYPE_UPLOAD_FILE:
                return 'UploadFile';
            case Enum::FORM_FIELD_TYPE_DROPDOWN:
                return 'Select';
            case Enum::FORM_FIELD_TYPE_EDITOR:
                return 'Editor';
            case FormField::FORM_FIELD_TYPE_TEXTAREA:
                return 'Textarea';
            case FormField::FORM_FIELD_TYPE_LABEL:
                return 'Text';
            case FormField::FORM_FIELD_TYPE_SPAN:
                return 'Span';
            default:
                throw new Exception("错误的类型~");
        }
    }
}