<?php
namespace Application\Service\DB\Dictionary;

use Application\Common\Exportenum;
use Application\Service\Extension\Helper\FormHelper;
use Application\Service\Extension\Helper\StringHelper;
use Application\Service\Extension\Laminas;
use Interop\Container\ContainerInterface;
use Laminas\Db\Sql\Predicate\Expression;
use Laminas\Db\Sql\Predicate\Operator;
use Laminas\Db\Sql\Where;

/**
 * @property integer $id
 * @property string $name 表单名称
 * @property integer $type 表单类型 0:一对一; 1:一对多
 * @property string $code 表单标识
 * @property integer $item_id 项目id
 * @property integer $group_id [yikeen_dictonary_from_group][id]
 * @property string $show_type 表单展示方式 top:顶部对齐 right:右对齐
 * @property integer $checklist_id 检查项表单id
 * @property integer$finish_condition 完成条件 0:任意一个; 1:全部;
 * @property integer $rdg_type 随机分组类型 1:新增;2:随机获取;
 * @property integer $order 排序
 * @property integer $is_del 是否删除
 * @property integer $is_show 是否展示
 * @property integer $is_patient 是否受试者填写 0:否; 1:是;
 * @property integer $is_required 是否必填 0:否 1:是
 * @property string $reference_file 参考文件
 * @property integer $create_time 创建时间
 * @property integer $update_time 更新时间
 * @property integer $create_user_id 创建人
 * @property integer $update_user_id 修改人
 * @property integer $is_form_relation 是否被设置成了已关联表单 0:否; 1:是;
 * @property string $var_name 表单变量名
 * @property integer $can_patient_write 受试者能否填写
 * @property string $origin_id origin_id 数据转移前表单ID
 * @property integer $content_id 旧系统 研究内容id
 * @property string $expression 计算公式
 * @property string $except_checktime 表单类型为贯穿全程类, 不在哪些检查点内显示
 * @property integer $is_handwritten_signature 是否手写签名 0:否 1:是
 * @property string $ds_stage 实验总结类表单隶属于哪个阶段 1:脱落 4:终止 3:完成
 * @property string $guide 填写指南
 * @property integer $is_using_score 是否是评分功能 0:否; 1:是
 * @property integer $is_field_score 时候有评分字
 * @property integer $is_through_process_do 是否是识别医嘱功能 0:否 1:是
 * @property integer $info_collect_type 信息采集类型
 */
class ItemForm extends Form
{
    /**
     * 需要处理的单选id, 关联表单有的是倒着添加的, 导致找不到对应的关联表单。
     * @var
     */
    private static array $radioId = [];

    public function __construct($dbAdapter, ContainerInterface $container)
    {
        if (!$this->tableName) {
            $this->tableName = 'yikeen_item_form';
        }

        parent::__construct($dbAdapter, $container);
    }

    public function getCreateTime()
    {
        return time();
    }

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

    public function getAeForm(int $itemId)
    {
        return Laminas::$serviceManager->itemForm->fetchOne([
            'where' => ['item_id' => $itemId, 'group_id' => FormGroup::AE, 'is_del' => 0]
        ]);
    }

    /**
     * 生成项目表单 code 值
     * @return string
     */
    public function generateFormCode(): string
    {
        return 'ITEM_' . StringHelper::generateHashValue();
    }

    /**
     * @return FormVersion
     */
    protected function getFormVersion(): FormVersion
    {
        return Laminas::$serviceManager->itemFormVersion;
    }

    /**
     * 获取脱离表单
     */
    public function getOutForm(int $itemId)
    {
        $outFormData = $this->fetchOne([
            'where' => [
                'group_id' => FormGroup::TEST_SUMMARY,
                'item_id' => $itemId,
                'is_del' => 0,
            ]
        ]);

        if (!$outFormData) {
            return [];
        }

        return $outFormData;
    }

    /**
     * @note 弹窗结构
     * @param int $itemId
     * @param int $customFormType   // 自定义表单类型
     * @return array
     */
    public function getItemFormOptions(int $itemId, int $customFormType = 0): array
    {
        $itemFormList = $this->fetchAll([
            'where' => ['is_del' => 0, 'item_id' => $itemId, 'is_export' => 0],
            'columns' => ['value' => 'id', 'label' => new Expression("CONCAT(name, '[ ', var_name, ' ]')")],
            'order' => ['group_id', 'order']
        ]);

        // 未使用的表单不显示
        $useFormIdList = $this->LocalService()->projectPatientworkbatch->fetchAll([
            'where' => [
                'item_id' => $itemId,
            ],
            'columns' => [ 'form_id'],
            'group' => 'form_id'
        ]);

        $useFormIdList = array_column($useFormIdList, 'form_id');
        $result = Exportenum::EXPORT_TYPE_MAP_CUSTOM_FORM[$customFormType];

        foreach($itemFormList as &$itemForm) {
            if(in_array($itemForm['value'], $useFormIdList)) {
                $result[] = $itemForm;
            }
        }

        return $result;
    }

    /**
     * 获取脱离表单
     */
    public function getOutFormV2(int $itemId, $patientStatus)
    {
        $outFormData = $this->fetchAll([
            'where' =>
                (new Where())
//                    ->nest()
//                    ->notEqualTo('group_id', FormGroup::TEST_SUMMARY)
//                    ->or
                    ->expression("FIND_IN_SET(?,ds_stage)", [$patientStatus])
//                    ->and
//                    ->equalTo('group_id', FormGroup::TEST_SUMMARY)
//                    ->unnest()
                    ->equalTo('item_id', $itemId)
                    ->and
                    ->equalTo('is_del', 0)

//                [
//                'group_id' => FormGroup::TEST_SUMMARY,
//                'item_id' => $itemId,
//                'is_del' => 0,
//                new \Laminas\Db\Sql\Predicate\Expression("FIND_IN_SET('$patientStatus',ds_stage)")
//            ]
        ]);

        if (!$outFormData) {
            return [];
        }

        return $outFormData;
    }

    /**
     * 复制表单
     * 从一个项目复制到另一个项目
     * @param int $originFormId 想要复制的项目id
     * @param int $formId 复制到的项目id
     */
    public function cloneForm(int $originFormId, int $formId,$checktimeMap,$fid)
    {
        $newItemId = $formId;
        // 获取所有表单
        $originData = $this->fetchAll([
            'where' => ['item_id' => $originFormId, 'is_del' => 0]
        ]);


        // 记录旧表单id和新表单id的映射、参照信息
        $formIdMap = $map = $fieldReferArr = $oldCheckArr = [];

        foreach ($originData as $originValue) {
            $insertId = $this->save([
                'name' => $originValue['name'],
                'item_id' => $formId,
                'group_id' => $originValue['group_id'],
                'type' => $originValue['type'],
                'is_del' => 0,
                'order' => $originValue['order'],
                'finish_condition' => $originValue['finish_condition'],
                'is_required' => $originValue['is_required'],
                'checklist_id' => $originValue['checklist_id'],
                'is_show' => $originValue['is_show'],
                'show_type' => $originValue['show_type'],
                'is_patient' => $originValue['is_patient'] ?: 0,
                'reference_file' => $originValue['reference_file'],
                'var_name' => $originValue['var_name'],
                'can_patient_write' => $originValue['can_patient_write'],
                'rdg_type' => $originValue['rdg_type'],
                'expression' => $originValue['expression'],
                'except_checktime' => $originValue['except_checktime'],
                'is_handwritten_signature' => $originValue['is_handwritten_signature'],
                'ds_stage' => $originValue['ds_stage'],
                'is_using_score' => $originValue['is_using_score'],
                'gco_pool' => $originValue['gco_pool'],
                'info_collect_type' => $originValue['info_collect_type'],
                'identification_edit' => $originValue['identification_edit'],
                'is_through_process_do' => $originValue['is_through_process_do'],
                'is_patient_general_info' => $originValue['is_patient_general_info'],
                'is_export' => $originValue['is_export'],
                'is_more_sdv' => $originValue['is_more_sdv']
            ]);

            // $formIdMap[旧表单id] = 新表单id
            $formIdMap[$originValue['id']] = $insertId;

            $this->LocalService()->itemCheckcontent->update([
                'form_id' => $insertId
            ], ['item_id' => $formId, 'form_id' => $originValue['id']]);

            // 字段表
            $fieldData = Laminas::$serviceManager->itemFormField->fetchAll([
                'where' => ['form_id' => $originValue['id'], 'version' => 'v1.0', 'is_del' => 0]
            ]);

            foreach ($fieldData as $datum) {
                $fieldId = Laminas::$serviceManager->itemFormField->save([
                    'form_id' => $insertId,
                    'name' => $datum['name'],
                    'type' => $datum['type'],
                    'is_list' => $datum['is_list'],
                    'is_export' => $datum['is_export'],
                    'order' => $datum['order'],
                    'rules' => $datum['rules'],
                    'version' => $datum['version'],
                    'is_del' => $datum['is_del'],
                    'parent' => $datum['parent'] ? $map[$datum['parent']] : 0,
                    'is_anchor' => $datum['is_anchor'] ?: 0,
                    'is_booked_time' => $datum['is_booked_time'] ?: 0,
                    'item_id' => $formId,
                    'var_name' => $datum['var_name'] ?: '',
                    'default' => $datum['default'],
                    'unit' => $datum['unit'],
                    'is_hyperwindow' => $datum['is_hyperwindow'],
                    'english' => $datum['english'],
                    'cut_pre' => $datum['cut_pre'],
                    'cut_after' => $datum['cut_after'],
                    'cut_start' => $datum['cut_start'],
                    'cut_length' => $datum['cut_length'],
                    'is_csae' => $datum['is_csae'],
                    'is_hide' => $datum['is_hide'],
                    'showfiled_name' => $datum['showfiled_name'],
                ]);

                $map[$datum['id']] = $fieldId;

                if(!empty($datum['checkname_id']) || !empty($datum['form_field_id'])){
                    $fieldReferArr[$fieldId] = [
                        'checkname_id'=>$datum['checkname_id'],
                        'form_field_id'=>$datum['form_field_id'],
                        'default_field_id'=>$datum['default_field_id'],
                        'default_field_type'=>$datum['default_field_type']
                    ];

                    if(!empty($datum['checkname_id'])){
                        $datum_checkname_arr = explode(',',$datum['checkname_id']);
                        foreach($datum_checkname_arr as $datum_checkname){
                            if(!empty($datum_checkname) && !in_array($datum_checkname,$oldCheckArr)){
                                $oldCheckArr[] = $datum_checkname;
                            }
                        }
                        unset($datum_checkname_arr);
                    }
                }
                Laminas::$serviceManager->itemChecktime->update([
                    'field_id' => $fieldId
                ], ['item_id' => $formId, 'field_id' => $datum['id']]);

                Laminas::$serviceManager->itemCheckname->update([
                    'form_field_id' => $fieldId,'form_id'=>$insertId
                ], ['item_id' => $formId, 'form_field_id' => $datum['id']]);
            }

            foreach ($fieldData as $k => $datum) {
                // text 表
                $textData = Laminas::$serviceManager->itemFormFieldText->fetchAll([
                    'where' => ['field_id' => $datum['id']]
                ]);


                foreach ($textData as $textDatum) {
                    $textId = Laminas::$serviceManager->itemFormFieldText->save([
                        'var_name' => $textDatum['var_name'],
                        'tips' => $textDatum['tips'],
                        'placeholder' => $textDatum['placeholder'],
                        'is_list' => $textDatum['is_list'],
                        'order' => $textDatum['order'],
                        'field_id' => $map[$datum['id']],
                        'form_id' => $insertId,
                    ]);
                }

                self::$radioId[$insertId][] = $datum['id'];
            }
        }

        //更新参照信息
        if(!empty($fieldReferArr)){
            $oldCheckNewArr = [];
            if(!empty($oldCheckArr)){
                $oldCheckNameArr = Laminas::$serviceManager->itemCheckname->fetchDataByKey([
                    'is_del' => 0,
                    new Operator('checkname_id', Operator::OP_GT, 0),
                    'id' => $oldCheckArr,
                ],['id','checkname_id'],['id'],'id',0);
                if(!empty($oldCheckNameArr)){
                    $oldCheckName_nameids = [];
                    foreach($oldCheckNameArr as $oldCheckNameidval){
                        $oldCheckName_nameids[$oldCheckNameidval['checkname_id']] = $oldCheckNameidval['checkname_id'];
                    }
                    if(!empty($oldCheckName_nameids)){
                        $nowCheckNameArr = Laminas::$serviceManager->itemCheckname->fetchDataByKey([
                            'is_del' => 0,
                            'item_id' => $formId,
                            'checkname_id' => array_values($oldCheckName_nameids),
                        ],['id','checkname_id'],['id'],'checkname_id',0);
                        foreach($oldCheckNameArr as $oldCheckNameid=>$oldCheckName_nameid){
                            $oldCheckNewArr[$oldCheckNameid] = isset($nowCheckNameArr[$oldCheckName_nameid['checkname_id']]) && !empty($nowCheckNameArr[$oldCheckName_nameid['checkname_id']]) ? $nowCheckNameArr[$oldCheckName_nameid['checkname_id']]['id'] : 0;
                        }
                        unset($nowCheckNameArr);
                    }
                }
                unset($oldCheckNameArr);
            }
            foreach($fieldReferArr as $fieldReferId=>$fieldReferInfo){
                //参照检查项
                $field_checkname_id = '';
                if(!empty($fieldReferInfo['checkname_id'])){
                    $old_field_checknames = explode(',',$fieldReferInfo['checkname_id']);
                    foreach($old_field_checknames as $old_field_checkname){
                        if(!empty($old_field_checkname) && isset($oldCheckNewArr[$old_field_checkname]) && !empty($oldCheckNewArr[$old_field_checkname])){
                            $field_checkname_id .= $oldCheckNewArr[$old_field_checkname].',';
                        }
                    }
                    $field_checkname_id = !empty($field_checkname_id) ? trim($field_checkname_id,',') : '';
                }
                //参照表单内容
                $field_form_field_id = '';
                if(!empty($fieldReferInfo['form_field_id'])){
                    $old_form_field_ids = explode(',',$fieldReferInfo['form_field_id']);
                    foreach($old_form_field_ids as $old_form_field_id){
                        if(!empty($old_form_field_id) && isset($map[$old_form_field_id]) && !empty($map[$old_form_field_id])){
                            $field_form_field_id .= $map[$old_form_field_id].',';
                        }
                    }
                    $field_form_field_id = !empty($field_form_field_id) ? trim($field_form_field_id,',') : '';
                }
                //默认值
                $default_field_id = 0;
                if(!empty($fieldReferInfo['default_field_id'])){
                    if($fieldReferInfo['default_field_type'] == 1){
                        $default_field_id = isset($oldCheckNewArr[$fieldReferInfo['default_field_id']]) && !empty($oldCheckNewArr[$fieldReferInfo['default_field_id']]) ? $oldCheckNewArr[$fieldReferInfo['default_field_id']] : 0;
                    }
                    if($fieldReferInfo['default_field_type'] == 2){
                        $default_field_id = isset($map[$fieldReferInfo['default_field_id']]) && !empty($map[$fieldReferInfo['default_field_id']]) ? $map[$fieldReferInfo['default_field_id']] : 0;
                    }
                }
                Laminas::$serviceManager->itemFormField->update(['checkname_id'=>$field_checkname_id,'form_field_id'=>$field_form_field_id,'default_field_id'=>$default_field_id,'default_field_type'=>$fieldReferInfo['default_field_type']],'id = '.$fieldReferId);
            }
            unset($oldCheckNewArr);
        }
        unset($fieldReferArr);
        unset($oldCheckArr);

        foreach (self::$radioId as $insertId => $radioId) {
            foreach ($radioId as $rid) {
                // radio 表
                $versionData = Laminas::$serviceManager->itemFormFieldRadio->fetchAll([
                    'where' => ['field_id' => $rid]
                ]);

                foreach ($versionData as $versionDatum) {
                    if ($versionDatum['relation_classification'] == ItemFormFieldRadio::RELATION_CLASSIFICATION_FORM) {
                        $radioMap = $formIdMap;
                    } elseif ($versionDatum['relation_classification'] == ItemFormFieldRadio::RELATION_CLASSIFICATION_FIELD) {
                        $radioMap = $map;
                    }

                    $relationInformation = FormHelper::handleRelationInformation($versionDatum['relation_information'], $radioMap);
                    Laminas::$serviceManager->itemFormFieldRadio->save([
                        'value' => $versionDatum['value'],
                        'is_check' => call_user_func(function () use ($versionDatum) {
                            if ($versionDatum['is_check'] === null) {
                                return 1;
                            }

                            return $versionDatum['is_check'];
                        }),
                        'relation_classification' => $versionDatum['relation_classification'],
                        'relation_type' => $versionDatum['relation_type'],
                        'relation_information' => $relationInformation,
                        'field_id' => $map[$rid],
                        'form_id' => $insertId,
                        'score' => $versionDatum['score'],
                        'is_score' => $versionDatum['is_score'],
                    ]);

                    // 设置表单关联关系
                    if ($versionDatum['relation_classification'] == ItemFormFieldRadio::RELATION_CLASSIFICATION_FORM) {
                        $relationFormId = explode(',', $relationInformation);
                        foreach ($relationFormId as $item) {
                            Laminas::$serviceManager->itemFormRelation->insert([
                                'form_id' => $insertId,
                                'field_id' => $map[$rid],
                                'relation_form_id' => $item
                            ]);
                        }
                    }
                }
            }
        }

        foreach ($formIdMap as $formId) {
            Laminas::$serviceManager->itemFormVersion->save([
                'version' => 'v1.0',
                'field' => Laminas::$serviceManager->itemForm->buildFieldVersion($formId),
                'form_id' => $formId,
            ]);
        }

        //如果大项目开启了EDC 则同步EDC逻辑核查公式
        $isEdc = $this->LocalService()->itemInfo->getOneFieldVal('is_edc',"id = $fid");
        if($isEdc == 1){
            $data = $this->LocalService()->itemPatientFormLogic->fetchAll([
                'where'=> [
                    'is_del' => 0,
                    'item_id' => $originFormId,
                ]
            ]);
            if(empty($data)) return true;
            foreach($data as $k=>$v){
                $arr = [];
                $arr['expression'] = $v['expression'];
                $arr['item_id'] = $newItemId;
                $array = explode("'",$v['generate_expression']);
                foreach($array as $key=>$value){
                    if(is_numeric($value)){
                        if(isset($checktimeMap[$value])){
                            $v['generate_expression'] = str_replace($value, $checktimeMap[$value], $v['generate_expression']);
                        }
                    }
                }

                $arr['generate_expression'] = $v['generate_expression'];
                $arr['expression_hash'] = StringHelper::generateHashValue();;
                $arr['note'] = $v['note'];
                $generator = unserialize($v['generator']);
                $generator->expression = $v['generate_expression'];
                $generator->itemId = $newItemId;
                $generator->expressHash = $arr['expression_hash'];

                foreach($generator->allusings as $kk=>$vv){
                    $tmpArr = explode('_',$vv);
                    if(isset($checktimeMap[$tmpArr[0]])){
                        $tmpArr[0] = $checktimeMap[$tmpArr[0]];
                    }
                    if(isset($checktimeMap[$formMap[1]])){
                        $tmpArr[1] = $checktimeMap[$tmpArr[1]];
                    }
                    if(isset($checktimeMap[$fieldMap[2]])){
                        $tmpArr[2] = $checktimeMap[$tmpArr[2]];
                    }
                    $generator->allusings[$kk] = implode('_',$tmpArr);
                }
                $arr['generator'] = serialize($generator);
                $this->LocalService()->itemPatientFormLogic->insert($arr);
            }
        }

        return [$formIdMap,$map];
    }

    /**
     * Notes: 获取指定信息下的表单ID
     * User: lltyy
     * DateTime: 2022/9/6 10:00
     *
     * @param string $form_where
     * @param string|array $group_where
     * @return mixed
     */
    public function getGroupForm(array $form_where= ['is_del' => 0], array $group_where = []){
        $form_id_arr = [];
        if(!empty($group_where)){
            $formgroup_id_arr = $this->LocalService()->dictionaryFormGroup->fetchCol('id',$group_where);
            if(!empty($formgroup_id_arr)){
                $form_where['group_id'] = $formgroup_id_arr;
            }
        }
        $form_id_arr = $this->fetchCol('id',$form_where);
        return $form_id_arr;
    }

    /**
     * @param $text
     * @return array
     */
    public static function splitField($text): array
    {
        $data = explode('-', $text);
        array_shift($data);
        $length = count($data);
        $result = [];
        for ($i = 0; $i < $length / 2; $i++) {
            $first = array_shift($data);
            $last = array_pop($data);
            $result[] = [$first, $last];
        }
        return $result;
    }


    /**
     * Notes:获取指定条件下的数据
     * @param string $where 条件
     * @param string[] $columns 字段
     * @param string[] $order 排序
     * @param string $key 键值
     * @param int $is_more 是否有多笔【1 是 0 否】
     * @return array
     * @return
     * @author haojinhua
     * @date 2024-05-28
     */
    public function fetchDataByKey($where='is_del = 0',$columns=['id'],$order=['id'],$key='id',$is_more=0){
        $datas = [];
        $cond = [
            'where'=>$where,
            'columns'=>$columns,
            'order'=>$order
        ];
        $infoDatas = $this->fetchAll($cond);
        if(!empty($infoDatas)){
            foreach($infoDatas as $infoData){
                $data_key = $infoData[$key];
                if($is_more == 1){
                    $datas[$data_key][] = $infoData;
                }else{
                    $datas[$data_key] = $infoData;
                }
            }
        }
        unset($cond);
        unset($infoDatas);
        return $datas;
    }
}
