<?php

namespace Application\Controller;

use Application\Common\DictionaryVarNameEnum;
use Application\Common\EventEnum;
use Application\Common\StatusCode;
use Application\Form\CmAEModel;
use Application\Form\item\patient\PatientFormModel;
use Application\Mvc\Controller\BasicController;
use Application\Service\DB\Db;
use Application\Service\DB\Dictionary\Form;
use Application\Service\Exceptions\InvalidArgumentException;
use Application\Service\Extension\Event;
use Application\Service\Extension\Events\FormEventHandler;
use Application\Service\Extension\Helper\ArrayHelper;
use Application\Service\Extension\Helper\DataHelper;
use Application\Service\Extension\Helper\SDMHelper;
use Application\Service\Extension\Helper\StringHelper;
use Application\Service\Extension\Laminas;
use Exception;
use Laminas\Db\ResultSet\ResultSet;
use Laminas\Db\Sql\Expression;
use Laminas\Db\Sql\Select;
use Laminas\Db\Sql\Sql;
use Laminas\Db\Sql\Where;
use Laminas\View\Model\JsonModel;


class CmController extends BasicController
{
    /**
     * @url /cm
     * @behavior CM_INDEX
     * @return JsonModel
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    public function indexAction(): JsonModel
    {
        $this->validator->attach(
            [['item_id', 'itemsig_id'], 'required'],
            [['patient_id', 'operate_user', 'status'], 'default', 'value' => 0],
        );

        if (!$this->validator->isValid()) {
            return $this->RenderApiJson()->Error(StatusCode::E_FIELD_VALIDATOR, $this->validator->getFirstErrorToString());
        }


        $this->validator->attributes['form_id'] = Laminas::$serviceManager->itemFormField->fetchOne(['where' => ['var_name' => DictionaryVarNameEnum::COLLECT_MEDICAL_TAKE_CMINDC, 'item_id' => $this->validator->attributes['item_id'], 'is_del' => 0]])['form_id'];
        if (!$this->validator->attributes['form_id']) {
            return $this->RenderApiJson()->Success();
        }

        $model = new PatientFormModel($this->validator);
        $model->setScenario($model::SCENARIO_CM_LIST);
        $where = new Where();
        $where->equalTo('cm.is_del', 0)->equalTo('cm.item_id', $this->validator->attributes['item_id'])->equalTo('cm.sign_id', $this->validator->attributes['itemsig_id'])->equalTo('cm.status', $this->validator->attributes['status']);

        if ($this->validator->attributes['patient_id']) {
            $searchStr = $this->validator->attributes['patient_id'];
            $searchPatientId = Laminas::$serviceManager->patient->fetchCol('id', [
                'item_id' => $this->validator->attributes['item_id'],
                "(patient_number LIKE '%{$searchStr}%' OR AES_DECRYPT( UNHEX( `patient_name` ), 'ykeEdc' ) LIKE '%{$searchStr}%')"
            ]);
            $where->nest()
                ->in('cm.patient_id', $searchPatientId)->or
                ->in('cm.update_user_id', [$this->validator->attributes['patient_id']])
                ->unnest();
        }

        //药物名称检索
        $serch_drug = isset($this->validator->attributes['serch_drug']) && $this->validator->attributes['serch_drug'] != '' ? trim($this->validator->attributes['serch_drug']) : '';
        if ($serch_drug != '') {
            $where->expression("JSON_SEARCH(content.data, 'all', ?)", "%$serch_drug%");
        }
        unset($serch_drug);

        $limit = $this->validator->attributes['limit'] ?: 10;
        $select = (new Select())
            ->from(['cm' => Laminas::$serviceManager->patientFormContentCm->getTableName()])
            ->join(['content' => Laminas::$serviceManager->patientFormContent->getTableName()], 'content.id = cm.content_id', ['id', 'update_user_id', 'update_time', 'data', 'checktime_id'], Select::JOIN_LEFT)
            ->where($where);
        $totalSqlObject = clone $select;
        $select->limit($limit)
            ->offset($limit * (Laminas::$app->getRequest()->getPost('page', 1) - 1));
        $res = function ($sqlObject) {
            $sql = new Sql(Laminas::$app->getServiceManager()->get('dbAdapter'));
            $statement = $sql->prepareStatementForSqlObject($sqlObject);
            $resultSet = new ResultSet();
            return $resultSet->initialize($statement->execute())->toArray();
        };
        $totalSqlObject->columns([new Expression('COUNT(`cm`.`id`) as `count`')]);

        $totalCount = intval($res($totalSqlObject)[0]['count'] ?? 0);
        $query = $res($select);

        $getCMINDCStatus = function($val) {
            if ($val == 0) {
                return '未判断>>';
            } elseif ($val == 1) {
                return '属于新增AE>>';
            } elseif ($val == 2) {
                return '属于已有AE>>';
            }

            return '非AE>>';
        };

        foreach ($query as &$item) {
            $operateUser = $item['update_user_id'];
            $updatedAt = $item['update_time'];
            $patientId = $item['patient_id'];
            $item = ArrayHelper::merge(current($model->getMultiView('', [$item])), [
                'patient_id_str' => SDMHelper::app()->patient->getPatientName($patientId) . ' [' . SDMHelper::app()->patient->getPatientNumber($patientId) . '] ',
                'operate_data' => $operateUser ? SDMHelper::app()->user->getRealName($operateUser) . ' / ' . date('Y-m-d H:i:s', $updatedAt) : date('Y-m-d H:i:s', $updatedAt),
                'cmindc_status_str' => $item['status'] == 0 ? '未判断' : $getCMINDCStatus($item['cmindc_status']),
//                'patient_id_str' => $item['status'] == 0 ? '未判断' : $getCMINDCStatus($item['cmindc_status']),
                'sign_id_str' => SDMHelper::app()->sign->getSignName($item['sign_id'])
            ]);
            $item['checktime_id_str'] = $item['checktime_id'] ? SDMHelper::app()->checkTime->getCheckName($item['checktime_id']) : '';
        }

        $table = ArrayHelper::remove(ArrayHelper::merge([
            ["label" => "受试者", "prop" => "patient_id_str"],
        ], Laminas::$serviceManager->itemForm->getPreviewConfig($this->validator->attributes['form_id'])['table'] ?? []), 'width');

        if ($this->validator->attributes['status'] == 1) {
            $table = ArrayHelper::merge($table, [
                ["label" => "操作人/操作时间", "prop" => "operate_data"],
            ]);
        }

        return $this->RenderApiJson()->Success($query, 'ok', [
            'total' => $totalCount,
            'table' => ArrayHelper::merge($table, [
                ["label" => "CM判断", "prop" => "cmindc_status_str"],
            ])
        ]);
    }

    /**
     * @url /cm/create
     * @behavior CM_CREATE
     * @return JsonModel
     * @throws Exception
     */
    public function createAction(): JsonModel
    {
        $this->validator->attach(
            [['patient_id', 'form_id', 'item_id', 'checktime_id', 'itemsig_id'], 'required'],
            [['patient_id', 'form_id', 'item_id', 'checktime_id', 'itemsig_id'], 'integer'],
        );

        $cmId = SDMHelper::app()->form->getCMINDCId($this->validator->attributes['form_id']);

        if (!$this->validator->isValid()) {
            return $this->RenderApiJson()->Error(StatusCode::E_FIELD_VALIDATOR, $this->validator->getFirstErrorToString());
        }

        // 受试者新增AE必须要添加数据
        if ($this->validator->attributes[$cmId] == 1 && !StringHelper::jsonDecode($this->validator->attributes['ae'], false)) {
            throw new InvalidArgumentException('请添加AE数据。');
        }

        if (!isset($this->validator->attributes[$cmId]) || !$this->validator->attributes[$cmId]) {
            throw new InvalidArgumentException(SDMHelper::app()->form->field->getName($cmId) . '不能为空。');
        }
        // 当用药原因（CM判断结果）不是其他，备注清空
        if( !$this->LocalService()->collectMedicaltake->isCmOptionsOther($this->validator->attributes[$cmId])) {
            $this->validator->setAttributes([
                'note' => ''
            ]);
        }

        $save_log_data = $this->validator->attributes;
        Event::on(EventEnum::AFTER_EVENT_CM_FORM_EDIT, [FormEventHandler::class, 'afterEventCmFormEdit']);

        $model = new PatientFormModel();

        $model->setPostValues($this->validator->attributes);

        $postData = DataHelper::handleFormData($this->validator->attributes, $this->params()->fromPost('form_id'));

        $model->setBeforeCommit(function() use ($model) {
            Event::trigger(EventEnum::AFTER_EVENT_CM_FORM_EDIT, [$model]);
        })->editForm($postData);

        $AEModel = new CmAEModel();
        // 属于新增AE
        if ($this->validator->attributes[$cmId] == 1) {
            $AEModel->createNewPatientAE();
        } elseif ($this->validator->attributes[$cmId] == 2) {
            if (!isset($this->validator->attributes['checked_content_id']) && !$this->validator->attributes['checked_content_id']) {
                throw new InvalidArgumentException('请选择关联的AE。');
            }
            $AEModel->setPostValues(ArrayHelper::merge([
                'cm_content_id' => $this->validator->attributes['id']
            ], $this->validator->attributes));
            $AEModel->createAlreadyHaveAE();
        } elseif (Laminas::$serviceManager->collectMedicaltake->fetchOne(['where' => ['id' => $this->validator->attributes[$cmId]]])['english'] === 'CMINDC4') {
            // 选的其他, 备注原因要必填
            if (!isset($this->validator->attributes['note']) && !$this->validator->attributes['note']) {
                throw new InvalidArgumentException('请填写原因。');
            }
            $AEModel->setPostValues(ArrayHelper::merge(['cm_content_id' => $this->validator->attributes['id']], ['note' => $this->validator->attributes['note']]));
            // 更新选中其他的有原因
            $AEModel->updateNote();
        }
        //日志存储
        if(!empty($this->validator->attributes['id'])){
            $this->LocalService()->log->saveFileLog($this->validator->attributes['id'],'ItemPatientformcontentcmlog',$save_log_data,1,'修改cm判断',$this->validator->attributes['item_id'],' ',['item_id'=>$this->validator->attributes['item_id']]);
        }
        unset($save_log_data);


        return $this->RenderApiJson()->Success([]);
    }

    /**
     * @url /cm/preview
     * @behavior CM_PREVIEW
     * @return JsonModel
     * @throws Exception
     */
    public function previewAction(): JsonModel
    {
        // 生成表单令牌 存储进redis 设置过期时间
        $only_keys1 = bin2hex(random_bytes(32));
        $redis = Laminas::$serviceManager->redisExtend->getRedisInstance();
        $redis->setex($only_keys1,3600,1);
        $this->validator->attach(
            [['id'], 'required'],
        );
        if (!$this->validator->isValid()) {
            return $this->RenderApiJson()->Error(StatusCode::E_FIELD_VALIDATOR, $this->validator->getFirstErrorToString());
        }
        $val = Laminas::$serviceManager->itemForm->setPreviewScenario(Form::SCENARIO_CM_LIST_VIEW)->getPreviewConfig($this->validator->attributes['id']);
        return $this->RenderApiJson()->Success($val,'OK',['only_keys1' => $only_keys1]);
    }

    /**
     * @url /cm/view
     * @behavior CM_VIEW
     * @return JsonModel
     * @throws Exception
     */
    public function viewAction(): JsonModel
    {
        $this->validator->attach(
            [['id'], 'required'],
        );

        if (!$this->validator->isValid()) {
            return $this->RenderApiJson()->Error(StatusCode::E_FIELD_VALIDATOR, $this->validator->getFirstErrorToString());
        }

        $model = new PatientFormModel();

        $val = $model->setScenario($model::SCENARIO_CM_LIST_VIEW)->viewById($this->validator->attributes['id']);

        // 如果选项是其他, 要把备注内容带出来
        $query = Laminas::$serviceManager->patientFormContentCm->fetchOne(['where' => ['content_id' => $this->validator->attributes['id']]]);
        if ($query && SDMHelper::app()->form->field->compareMedicalTake($query['cmindc_status'], 'CMINDC4')) {
            $val['note'] = $query['note'];
        }

        return $this->RenderApiJson()->Success($val);
    }

    /**
     * @url /cm/ae/index
     * @behavior CM_AE_INDEX
     * @return JsonModel
     * @throws Exception
     */
    public function aeListAction(): JsonModel
    {
        $this->validator->attach(
            [['item_id'], 'required'],
        );

        if (!$this->validator->isValid()) {
            return $this->RenderApiJson()->Error(StatusCode::E_FIELD_VALIDATOR, $this->validator->getFirstErrorToString());
        }

        $model = new CmAEModel();
        $model->setPostValues($this->validator->attributes);
        $val = $model->getNewAEList();

        return $this->RenderApiJson()->Success($val);
    }

    /**
     * @url /cm/ae/view
     * @behavior CM_AE_VIEW
     * @return JsonModel
     * @throws Exception
     */
    public function aeListViewAction(): JsonModel
    {
        $this->validator->attach(
            [['id', 'item_id', 'patient_id', 'ae_type'], 'required']
        );

        if (!$this->validator->isValid()) {
            return $this->RenderApiJson()->Error(
                StatusCode::E_FIELD_VALIDATOR,
                $this->validator->getFirstErrorToString()
            );
        }
        $model = new PatientFormModel();
        $model->setPostValues($this->validator->attributes);

        $res = [];
        if ($this->validator->attributes['ae_type'] == 2) {
            $query = Laminas::$serviceManager->itemCsaeRelation->fetchAll([
                'where' => [
                    'patient_id' => $this->validator->attributes['patient_id'],
                    'is_del' => 0
                ]
            ]);
        } elseif ($this->validator->attributes['ae_type'] == 1) {
            $query = Laminas::$serviceManager->itemCsaeRelation->fetchAll([
                'where' => [
                    'cm_content_id' => $this->validator->attributes['id'],
                    'is_del' => 0
                ]
            ]);
        }

        foreach ($query as $item) {
            $res[] = [
                'data' => Laminas::$serviceManager->itemPatientAeContent->fetchOne(['where' => ['branch' => $item['branch'], 'is_del' => 0]])['data'],
                'id' => $item['content_id'],
                'branch' => $item['branch']
            ];
        }

        $data = $res;

        $res = [];

        if ($data) {
            $res = $model->viewAe($data);
            if ($this->validator->attributes['ae_type'] == 2) {
                foreach ($res as &$resItem) {
                    $resItem['is_bind'] = Laminas::$serviceManager->itemCsaeChecked->fetchOne([
                        'where' => [
                            'is_del' => 0,
                            'branch' => $resItem['branch'],
                            'cm_content_id' => $this->validator->attributes['id']
                        ]
                    ]) ? 1 : 0;
                }
            }
        }

        return $this->RenderApiJson()->Success($res, 'OK');
    }

    /**
     * @url /cm/ae/viewRow
     * @behavior CM_AE_VIEW_ROW
     * @return JsonModel
     * @throws Exception
     */
    public function aeViewRowAction(): JsonModel
    {
        $data = Laminas::$serviceManager->itemPatientAeContent->fetchOne([
            'where' => ['id' => $this->params()->fromPost('id')]
        ]);

        $data['content_id'] = $this->LocalService()->itemPatientAeContent->getOneFieldVal('id', [
            'branch' => $data['branch']
        ]);

        $model = new PatientFormModel($this->validator);

        $res = json_decode($data['data'], true);
        $res['id'] = $this->params()->fromPost('id');

        return $this->RenderApiJson()->Success($model->viewById(0, $data));
    }

    /**
     * @url /cm/ae/edit
     * @behavior CM_AE_EDIT
     * @return JsonModel
     * @throws Exception
     */
    public function aeEditAction(): JsonModel
    {
        $this->validator->attach(
            [['id'], 'required'],
        );

        if (!$this->validator->isValid()) {
            return $this->RenderApiJson()->Error(StatusCode::E_FIELD_VALIDATOR, $this->validator->getFirstErrorToString());
        }

        $model = new CmAEModel();

        // $model->setPostValues($this->validator->attributes);

        $model->editAEForm();

        return $this->RenderApiJson()->Success([]);
    }

    /**
     * @url /cm/ae/delete
     * @behavior CM_AE_DELETE
     * @return JsonModel
     * @throws Exception
     */
    public function aeDeleteAction()
    {
        $this->validator->attach(
            [['content_id', 'cm_content_id'], 'required'],
        );

        if (!$this->validator->isValid()) {
            return $this->RenderApiJson()->Error(StatusCode::E_FIELD_VALIDATOR, $this->validator->getFirstErrorToString());
        }

        Db::beginTransaction();

        $cmindcStatus = Laminas::$serviceManager->patientFormContentCm->fetchOne([
            'where' => ['content_id' => $this->validator->attributes['cm_content_id']]
        ]);

        // 已有AE
        if ($cmindcStatus['cmindc_status'] == 2) {
            // 删除已有AE
            if (SDMHelper::app()->ae->discardCMListIsAlreadyAE($this->validator->attributes['content_id'], $this->validator->attributes['cm_content_id']) === false) {
                // 如果都删除干净了, 就要弄到带判断列表内
                SDMHelper::app()->ae->setCMAEEstimate($this->validator->attributes['cm_content_id']);
                SDMHelper::app()->ae->flushCMINDCContent($this->validator->attributes['cm_content_id']);
            }
        } elseif($cmindcStatus['cmindc_status'] == 1) {
            // 新增AE
            SDMHelper::app()->ae->discardCMNewAE($this->validator->attributes['cm_content_id'], $this->validator->attributes['content_id']);
            if (!Laminas::$serviceManager->itemCsaeRelation->fetchAll([
                'where' => ['cm_content_id' => $this->validator->attributes['cm_content_id'], 'is_del' => 0]
            ])) {
                SDMHelper::app()->ae->setCMAEEstimate($this->validator->attributes['cm_content_id']);
                SDMHelper::app()->ae->flushCMINDCContent($this->validator->attributes['cm_content_id']);
            }
        }

        Db::commit();

        //异步处理访视进度情况信息
        $this->LocalService()->swTaskClient->send([
            'svName' => 'projectPatientworkbatch',
            'methodName' => 'multipleUpdateData',
            'params' => [
                'item_id' => $cmindcStatus['item_id'],
                'itemsig_id' => $cmindcStatus['sign_id'],
                'patient_id' => $cmindcStatus['patient_id'],
                'checktime_id' => 0,
                'form_id' => $cmindcStatus['form_id'],
                'operate_type'=>11,
                'content_arr' => !empty($this->validator->attributes['cm_content_id']) ? [$this->validator->attributes['cm_content_id']] : [],
                'user_id' => $this->LocalService()->identity->getId()
            ]
        ]);

        return $this->RenderApiJson()->Success([]);
    }
}
