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

use Application\Command\Swoole\Server\WebSocketCommand;
use Application\Service\Extension\ErrorHandler;
use Interop\Container\ContainerInterface;
use Swoole\Coroutine\Http\Client;
use Laminas\Db\TableGateway\TableGateway;
use function Co\run;
use Application\Common\Enum;
use Laminas\Db\Sql\Predicate\Like;

class Configtable extends \Application\Service\DB\AbstractDb
{
    private $item_id;

    private $senddata;

    private $sqldata;

    private $sqlcount;

    private $site_item;

    private $hash;

    private $Adapter;

    private $table_name = ['yikeen_item_csae_checked','yikeen_item_csae_relation','yikeen_item_file','yikeen_item_form_field_radio','yikeen_item_form_field_text','yikeen_item_form_group','yikeen_item_form_relation','yikeen_item_form_version','yikeen_item_identificationresult','yikeen_item_patient_form_unlock','yikeen_item_reply','yikeen_item_superrole','yikeen_signatory_user','yikeen_signatory_info','yikeen_admin_user','yikeen_dictionary_form_group'];

    private $unisdelTable = ['yikeen_item_centerdata','yikeen_item_form_field_radio','yikeen_item_form_field_text','yikeen_item_form_version','yikeen_item_informedconsent_sign','yikeen_item_jobstaff'];

    private $realrole;

    private $sqldata_number = 1;

    private $type;
    //是否是第一次传输  0 第一次  1非第一次
    private $is_send = 0;

    //第二次传输 含有表单的表数组
    private $formTableName = ['yikeen_item_patient_form','yikeen_item_patient_form_content','yikeen_item_patient_ae_content'];

    //必填字段数组
    private $Fieldrequired;

    //必填字段未填写数组
    private $Requiredfilled;


    private $lockdata;

    public function __construct($dbAdapter, ContainerInterface $container)
    {
        $this->tableName = 'yikeen_config_tablename';
        parent::__construct($dbAdapter, $container);
    }

    private function _getWhere($type,$table_name)
    {
        $where['where'] = "1=1";
        //是否有项目id字段，并且判断大小项目
        if(!in_array($table_name,$this->table_name)){
            if($table_name == 'yikeen_item_info'){
                $where['where'] = "id = $this->item_id or fid = $this->item_id";
            }else{
                if($type == 1){
                    $where['where'] = "item_id = ".$this->item_id;
                }else{
                    $where['where'] = "item_id in "."($this->site_item)";
                }
            }
        }
        //是否有is_del字段
        if(!in_array($table_name,$this->unisdelTable)){
            $where['where'] .= " and is_del = 0";
        }
        $where['order'] = "id";
        return $where;
    }


    //查询项目数据，进行项目发送
    public function handleData($data)
    {
        $item_id = $data['item_id'];
        $hash = $data['hash'];
        $this->type = $data['type'];

        //是否删除、大表分批处理
        //大项目
        $this->item_id = $item_id;
        //hash值
        $this->hash = $hash;
        //小项目
        $itemidArr = $this->LocalService()->itemInfo->fetchCol('id','is_del = 0 and fid = '.$item_id);//获取项目名称

        $this->site_item = implode(',',$itemidArr);
//        $this->site_item = 2236;

        //查询EDC锁定的数据
        $itemidArr = $this->LocalService()->EdcLock->fetchAll(['where'=>"is_del = 0 and item_id in ($this->site_item)",'columns'=>['checktime_id','form_id','patient_id']]);//获取项目名称
        if(!empty($itemidArr)){
            $lockdata = [];
            foreach($itemidArr as $k=>$v){
                $lockdata[$v['patient_id'].'-'.$v['checktime_id'].'-'.$v['form_id']] = 1;
            }
            $this->lockdata = $lockdata;
        }


        if($this->type == 1){
            $tableWhere['where'] = "id = 61";
        }else{
            $tableWhere['where'] = "is_del = 0 and is_sync = 0";
        }
        $tableWhere['columns'] = ['id','table_name','table_name_db','table_type'];
        $tableDatas = $this->fetchAll($tableWhere);
        $this->createdir(APP_PATH . '/data/senddata'); //创建数据文件夹
        $this->createdir(APP_PATH . '/data/sendsql');  //创建sql文件夹
        //创建本次传输文件夹
        $datapath = APP_PATH . '/data/senddata/'.$this->hash;
        $sqlpath = APP_PATH . '/data/sendsql/'.$this->hash;
        $this->createdir($datapath);
        $this->createdir($sqlpath);



        //=========================
            //查询是否是第一次传输
//            $senddata = $this->LocalService()->Send->fetchone(['where'=>"item_id = $this->item_id",'columns'=>['id']]);
//            if(!empty($senddata))$this->is_send =1;
        //=========================
//        $this->formfieldrequireddata($this->site_item);
        foreach($tableDatas as $k=>$v){
//            if(!in_array($v['id'],[123])) continue;
                //查询本库数据
            $this->sdmData($v);
        }


    }

    public function createdir($path)
    {
        if(file_exists($path) == false)
        {
            mkdir($path, 0777, true);
            chmod($path,0777);
        }
        return true;
    }

    /**
     * Notes :处理数据
     * @param $arr
     * @return bool
     * Author:唐伯虎不虎
     * Date:2023/3/29 11:49
     */
    public function sdmData($arr)
    {
        set_time_limit(0);
        if(empty($arr['table_name_db'])) return false;
        $table = $arr['table_name_db'];
        $where = $this->_getWhere($arr['table_type'],$arr['table_name']);

        if($arr['table_name'] == 'yikeen_item_patient_form_content_updated'){
            //查询上次同步时间
            $sendWhere['where'] = "table_id = 123 and ";
            $sendWhere['group'] = ['table_id'];
            $sendWhere['order'] = ['id'];
            $sendWhere['columns'] = ['create_time'];
            $end_time = $this->LocalService()->Send->fetchOne($sendWhere);
            if(!empty($end_time)){
                $where['where'] .= " and create_time > ".$end_time['create_time'];
            }
        }
        if($arr['table_name'] == 'yikeen_real_rolesignatoryrelation'){
            $where['where'] .= " and role_id in (".implode(',',$this->realrole).")";
        }
        //====================
        if($this->is_send == 1 && in_array($arr['table_name'],$this->formTableName)){
            $where['where'] .= " and is_lock = 1";
        }
        //====================

        $count = $this->LocalService()->$table->getCount($where['where']);

        if(empty($count)){
            $sendarr['table_id'] = $arr['id'];
            $sendarr['batch'] = $this->hash;
            $sendarr['send_type'] = 0;
            $sendarr['item_id'] = $this->item_id;
            $this->LocalService()->Send->save($sendarr);
            return false;
        }

        $page = ceil($count / 5000);

        $data = $this->yieldDbData($page, $where,$table,$arr);

        $sqlData = '';
        //删除当前项目所有数据

        if(!in_array($arr['table_name'],$this->table_name)){
            if($arr['table_name'] == 'yikeen_item_info'){
                $this->sqldata .= 'DELETE FROM '.$arr['table_name'].' WHERE id = '.$this->item_id.' or id in ('.$this->site_item.')'.';'."\r\n";
            }else{
                if($arr['table_type'] == 1){
                    $this->sqldata .= 'DELETE FROM '.$arr['table_name'].' WHERE item_id = '.$this->item_id.';'."\r\n";
                }else{
                    $this->sqldata .= 'DELETE FROM '.$arr['table_name'].' WHERE item_id in ('.$this->site_item.');'."\r\n";
                }
            }
        }else{
            $this->sqldata .= 'DELETE FROM '.$arr['table_name'].' WHERE id > 0;'."\r\n";
        }
        $attrDatas = [];
        if($arr['table_name'] == 'yikeen_item_patient'){
            //查询受试者拓展属性---隐私属性
            $attrDatas = $this->LocalService()->patientattrs->fetchCol('id',"item_id in (".$this->site_item.") and is_del = 0 and is_hide = 1");
        }

        foreach($data as $k=> $value){

            foreach($value as $kk=>$vv){

                //锁定数据不进行转移 $this->lockdata
                if($arr['table_name'] == 'yikeen_item_patient_form' || $arr['table_name'] == 'yikeen_item_patient_form_content' || $arr['table_name'] == 'yikeen_item_patient_ae_content'){
                    if(empty($vv['checktime_id'])) $vv['checktime_id'] = 0;
                    if(isset($this->lockdata[$vv['patient_id'].'-'.$vv['checktime_id'].'-'.$vv['form_id']])) continue;
                }

                if($arr['table_name'] == 'yikeen_real_role'){
                    $this->realrole[] = $vv['id'];
                }

                //虚拟键删除字段
                if($arr['table_name'] == 'yikeen_item_patient')unset($vv['patient_number_name']);
                if($arr['table_name'] == 'yikeen_item_info')unset($vv['item_number_name']);

                if($arr['table_name'] == 'yikeen_item_patient' && !empty($attrDatas)){
                    $patient_content = json_decode($vv['patient_content'],true);
                    foreach($patient_content as $contentK =>$contentV){
                        if(in_array($contentV['id'],$attrDatas)){
                            if($contentV['field'] == 'number') $vv['patient_number'] = '';
                            if($contentV['field'] == 'name') $vv['patient_name'] = '';
                            if($contentV['field'] == 'sex') $vv['patient_sex'] = '';
                            if($contentV['field'] == 'ns') $vv['patient_name_easy'] = '';
                            unset($patient_content[$contentK]);
                        }
                    }
                    $vv['patient_content'] = json_encode($patient_content,true);
                }

                //json转移
                if($arr['table_name'] == 'yikeen_patient_checktime_list'){
                    $vv['item_checktime_list'] = trim(json_encode($vv['item_checktime_list'],true),'"');
                }
                if($arr['table_name'] == 'yikeen_item_form_version'){
                    $vv['field'] = trim(json_encode($vv['field'],true),'"');
                }
                if($arr['table_name'] == 'yikeen_item_patient_form_content'){
                    $vv['data'] = trim(json_encode($vv['data'],true),'"');
                }

                if($k == 0){
                    $field = '`'.implode('`,`',array_keys($vv)).'`';
                }
                $values = "'".implode("','",array_values($vv))."'";

                $this->sqldata.= 'INSERT INTO '.$arr['table_name'].' ('.$field.') VALUES('.$values.')'.';'."\r\n";

                $value[$vv['id']] = $vv;
                unset($value[$kk]);

            }
            $this->sqlcount += count($value);
            file_put_contents(APP_PATH.'/data/senddata/'."$this->hash".'/'.$arr['table_name'].$k.'.txt',json_encode($value),FILE_USE_INCLUDE_PATH);
        }

        if($this->sqlcount >= 10000){
            if($this->type == 1) $this->sqldata_number += 100;
            file_put_contents(APP_PATH.'/data/sendsql/'."$this->hash".'/'.$this->sqldata_number.'.sql',$this->sqldata,FILE_USE_INCLUDE_PATH);
            $this->sqldata = '';
            $this->sqlcount = 0;
            $this->sqldata_number += 1;
        }elseif($arr['table_name'] == 'yikeen_signatory_user'){
            file_put_contents(APP_PATH.'/data/sendsql/'."$this->hash".'/'.$this->sqldata_number.'.sql',$this->sqldata,FILE_USE_INCLUDE_PATH);
        }
        elseif($arr['table_name'] == 'yikeen_item_identificationresultchange'){
            if($this->type == 1) $this->sqldata_number += 100;
            file_put_contents(APP_PATH.'/data/sendsql/'."$this->hash".'/'.$this->sqldata_number.'.sql',$this->sqldata,FILE_USE_INCLUDE_PATH);
        }
        unset($data);
        unset($sqlData);
        //添加记录
        $sendarr['table_id'] = $arr['id'];
        $sendarr['batch'] = $this->hash;
        $sendarr['send_type'] = 1;
        $sendarr['item_id'] = $this->item_id;
        $this->LocalService()->Send->save($sendarr);
        return true;
    }
    /*
     * 通过yield从数据库中分批取出数据，也是为了防止数据量过大一次性抓取数据，导致内存溢出的情况
     */
    public function yieldDbData($page, $syslogWhere,$table,$arr){
        $limit = 5000;
        for($i = 1; $i <= $page; $i++){
            $offset = ($i - 1) * $limit;
            $syslogWhere['limit'] = $limit;
            $syslogWhere['offset'] = $offset;
            $tableData = $this->LocalService()->$table->fetchAll($syslogWhere);
            yield $tableData;
        }
    }

    /**
     * Notes : 贯穿全程表单实时传输
     * Author:唐伯虎不虎
     * Date:2023/4/24 15:17
     */
    public function runthroughForm(int $patientform_id,int $patientformcontent_id,bool $is_ae = false,$adapter)
    {
        $yikeen_item_patient_form = new TableGateway('yikeen_item_patient_form', $adapter);
        $yikeen_item_patient_form_content = new TableGateway('yikeen_item_patient_form_content', $adapter);

        $patientform_id = 197930;
        $patientformcontent_id = 196529;

        //查询数据
        $patientformArr = $this->LocalService()->patientForm->fetchOne(['where'=>"id = $patientform_id"]);
        $patientformcontentArr = $this->LocalService()->patientFormContent->fetchOne(['where'=>"id = $patientformcontent_id"]);


        //处理受试者填写表单记录表
        $is_patientform = $yikeen_item_patient_form->select(["id" => $patientform_id])->current();
        if($is_patientform){
            //修改
            $yikeen_item_patient_form->update($patientformArr);
        }else{
            //添加
            $yikeen_item_patient_form->insert($patientformArr);
        }
        //处理受试者表单数据表
        $is_patientform = $patientformcontentArr->select(["id" => $patientformcontent_id])->current();
        if($is_patientform){
            //修改
            $patientformcontentArr->update($patientformArr);
        }else{
            //添加
            $patientformcontentArr->insert($patientformArr);
        }
    }


    /**
     * 表单字段必填数据处理
     * 如果字段必填，受试者表单填写、则记录数据、如果表单没有填写则不记录
     */
    public function formfieldrequireddata($site_item)
    {
        $site_item = explode(',',$site_item);
        //查询当前项目所有必填字段
        $fieldrequiredWhere['where'] = "is_del = 0 and item_id in (".$site_item.") and rules like '".'%"v-required";s:1:"1"%'."'";
        $fieldrequiredWhere['columns'] = ['id','signatory_id','varname'];
        $fieldrequireddatas = $this->LocalService()->itemFormField->fetchAll(['where'=>[
            'item_id' => $site_item,
            new Like('rules', '%"v-required";s:1:"1"%')
        ],'columns'=>['id','name','form_id','item_id']]);
        if(!empty($fieldrequireddatas)){
            foreach($fieldrequireddatas as $k=>$v){
                $this->Fieldrequired[$v['item_id'].'-'.$v['form_id']][] = $v['id'];
            }
        }else{
            return false;
        }
    }
}