<?php
namespace app\controller;

use app\model\CdssXyDisease;
use app\model\XyZskDisease;
use think\facade\Log;
use think\facade\Request;
use think\response\Json;


/**
 * Es学科分析
 */
class EsDepartment extends CommonEsController
{

    /**
     * 首页
     *
     * @param string  $value
     * @param string  $year
     * @param string  $tag
     * @return Json
     */
    public function index():Json
    {
        $selectValue = Request::param('value')  ?? '';
        $year = Request::param('year')   ?? '';
        $tag  = Request::param('tag')    ?? 'disease';
        if( ! $selectValue || ! $year) {
            return $this->_json_error('参数请求有误！');
        }

        /**
         * 单个｜多个 疾病
         */
        if('disease' === $tag) {
            if(stripos($selectValue, ',') !== false) {
                $diseaseList = explode(',' , $selectValue);
            } else {
                $diseaseList = $selectValue;
            }
        }

        /**
         * 某个科室下疾病
         */
        if('department' === $tag) {
            $diseaseList = $this->getDiseaseByDepartment($selectValue);
        }

        /**
         * es查询数据
         */
        $esData = $this->esQuery($diseaseList , $year);

        /**
         * 相关的发文总量
         */
        $total = $esData['hits']['total'];

        /**
         * 主要主题统计
         */
        $subjectTop = $esData['aggregations']['subjectTop']['buckets'][0]['doc_count'] ?? 0;;

        /**
         * 次要主题统计
         */
        $subjectSub = $esData['aggregations']['subjectSub']['buckets'][0]['doc_count'] ?? 0;

        /**
         * 被引用文章数量
         */
        $citedCnt = $esData['aggregations']['citedCnt']['doc_count'];

        /**
         * 总的被引量
         */
        $totalCitationCnt = $esData['aggregations']['citedCnt']['totalCitationCnt']['value'];

        /**
         * 最高单篇被引量
         */
        $maxCitation = $esData['aggregations']['citedCnt']['maxCitation']['value'];

        /**
         * 篇平均被引量
         */
        $citationsPerArticleAverageNumber = 0 == $citedCnt ? 0 : ceil($totalCitationCnt / $citedCnt);

        /**
         * 合作成功数
         */
        $successCopOrg = $esData['aggregations']['successCopOrg']['doc_count'];

        /**
         * 合作机构数
         */
        $corOrgCnt = $esData['aggregations']['successCopOrg']['corOrgCnt']['value'];

        /**
         * 合作学者数
         */
        $corAuthorCnt = $esData['aggregations']['successCopAuthor']['corAuthorCnt']['value'];

        /**
         * 被引用的文献总作者数量
         */
        $citedAuthorCnt =  $esData['aggregations']['citedCnt']['citedAuthorCnt']['value'];

        /**
         * 总的发文作者数量
         */
        $totalAuthorCnt = $esData['aggregations']['totalAuthorCnt']['value'];

        /**
         * 作者人均发文量
         */
        $authorPerArticleNum = 0 == $totalAuthorCnt ? 0 : round($total / $totalAuthorCnt , 2);

        /**
         * 作者人均被引量
         */
        $authorPerCitation = 0 == $citedAuthorCnt ? 0 : round($citedCnt / $citedAuthorCnt , 2);

        /**
         * 被引趋势
         */
        $postTrend = $esData['aggregations']['docStat']['buckets'];
        $citedTrend = [];
        foreach ($postTrend as $key => $value) {
            $citedTrend[$key]['key']       = $value['key'];
            $citedTrend[$key]['doc_count'] = $value['citedPerYear']['value'];
        }

        $relevantScholars    = $esData['aggregations']['topAuthors']['buckets'];
        $newRelevantScholars = [];
        foreach($relevantScholars as $key => $value) {
            $arr = explode('#' , $value['key']);
            $newRelevantScholars[$key]['key']       = $arr[0];
            $newRelevantScholars[$key]['org']       = $arr[1];
            $newRelevantScholars[$key]['doc_count'] = $value['doc_count'];
            //$newRelevantScholars[$key]['org']       = $this->getOrganization($value['key']);
        }

        /**
         * 数据返回
         */
        $esDepartment = [
            /**
             * 查询值
             */
            'value' => $selectValue ,

            /**
             * 数据统计
             */
            'count' => [
                /**
                 * 学术生产力
                 */
                'academic_productivity' => [
                    'doc_num'     => $total ,
                    'subject_top' => $subjectTop ,
                    'subject_sub' => $subjectSub ,
                ],

                /**
                 * 学术影响力
                 */
                'academic_influence' => [
                    'cited_amount' => $totalCitationCnt ,                                               // 被引量
                    'highest_single_article_citation_amount' => 0 == $total ? 0 : $maxCitation,         // 最高单篇被引量
                    'citations_per_article_Average_number'   => $citationsPerArticleAverageNumber ,     // 篇平均被引量
                    'cited_rate'   => 0 == $total ? 0 : round($citedCnt / $total , 2) ,   // 被引率
                ] ,

                /**
                 * 合作共创力
                 */
                'cooperation_creativity' => [
                    'partner_success_num'      => $successCopOrg ,   // 合作成功数
                    'partner_organization_num' => $corOrgCnt ,       // 合作成功数
                    'partner_author_num'       => $corAuthorCnt ,    // 合作成功数

                ] ,

                /**
                 * 科研学者力
                 */
                'power_scientific_research_scholar' => [
                    'publish_doc_author_num' => $citedAuthorCnt,        // 发文作者数
                    'author_per_article_num' => $authorPerArticleNum ,  // 作者人均发文量
                    'author_per_citation'    => $authorPerCitation ,    // 作者人均被引量
                ]
            ] ,


            /**
             * 统计图
             */
            'detail_analyse' => [
                'post_trend'           => $postTrend  ,                                        // 发文趋势
                'cited_trend'          => $citedTrend ,                                        // 被引趋势
                'subject_infiltration' => $esData['aggregations']['topSubject']['buckets'] ,   // 学科渗透
                'research_topic'       => $esData['aggregations']['keywordCnt']['buckets'] ,   // 研究主题
                'hot_body'             => $esData['aggregations']['topOrgs']['buckets'] ,      // 热门机构
                'relevant_scholars'    => $newRelevantScholars ,                               // 相关学者
                'subject_top'          => $esData['aggregations']['subjectTop']['buckets'],    // 主要主题
                'subject_sub'          => $esData['aggregations']['subjectSub']['buckets'],    // 次要主题
            ]
        ];

        return $this->_json_succ(
            $esDepartment
        );
    }


    /**
     * 获取学者机构
     */
    protected function getOrganization($author)
    {
        $index   = $this->currentLanguage();
        $params  = [
            'index' => $index ,
            'body'  => [
                'query' => [
                    'bool' => [
                        'filter' => [
                            'term' => [
                                'author_list.keyword' => $author
                            ]
                        ]
                    ]
                ],
                'size' => 30
            ]
        ];

        $client = $this->getEsClient();
        $result = $client->search($params);

        $total  = $result['hits']['total'];
        $data   = $result['hits']['hits'];

        $org['org'] = '';
        if(0 == $total) {
            return $org;
        }

        $source        = array_column($data   , '_source');
        $authorOrgList = array_column($source , 'author_org_list');

        $str = [];
        foreach($authorOrgList as $key => $value) {
            if (!is_array($value)){
                continue;
            }
            $valueCount = count($value);
            for ($i=0; $i<$valueCount; $i++) {
                $orgAuthor = $value[$i];
                if(stripos($orgAuthor , $author) !== false) {
                    $str = $orgAuthor;
                }
            }
        }

        if(empty($str)) {
            return $org;
        }

        $authorOrgArr = explode('#' , $str);
        $org = $authorOrgArr[1] ?? '';
        return $org;
    }


    /**
     * 某个科室下疾病
     *
     * @param  string  $department
     * @return array
     */
    protected function getDiseaseByDepartment($department):array
    {
        $singleDepartmentDiseases = XyZskDisease::field('name , departmentLevel1 as department')->withSearch('departmentLevel1' ,
            [
                'departmentLevel1' => $department
            ]
        )->select()->toArray();

        if(empty($singleDepartmentDiseases)) {
            $singleDepartmentDiseases = [];
        }
        return array_column(
            $singleDepartmentDiseases , 'name'
        );
    }


    /**
     * es-query查询
     *
     * @param  string|array  $diseaseList
     * @param  string        $year
     * @return array
     */
    protected function esQuery($diseaseList , $year):array
    {
        $yearArr = explode(',', $year);
        if(is_array($diseaseList)) {
            foreach($diseaseList as $disease) {
                $should[] = [
                    'match_phrase' => [
                        'title' => $disease
                    ]
                ];
            }
        } else {
            $disease  = $diseaseList;
            $should[] = [
                'match_phrase' => [
                    'title' => $disease
                ]
            ];
        }

        $params = [
            'index' => $this->currentLanguage(),
            'body'  => [
                'size'  => 20 ,
                'query' => [
                    'bool' => [
                        'must' => [
                            [
                                'range' => [
                                    'year' => [
                                        'gte' => $yearArr[0] ,
                                        'lte' => $yearArr[1]
                                    ]
                                ]
                            ]
                        ] ,
                        'should' => [
                            $should
                        ] ,
                        'minimum_should_match' => 1
                    ]
                ] ,
                'aggs' => [
                    'topSubject' => [
                        'terms' => [
                            'field' => 'subject_top_list.keyword' ,
                            'order' => [
                                '_count' => 'desc'
                            ] ,
                            'size' => 10
                        ]
                    ] ,
                    'topAuthors' => [
                        'terms' => [
                            'field' => 'author_org_list.keyword' ,
                            'order' => [
                                '_count' => 'desc'
                            ] ,
                            'size' => 15
                        ]
                    ],
                    'topOrgs' => [
                        'terms' => [
                            'field' => 'organization_parsed.keyword' ,
                            'order' => [
                                '_count' => 'desc'
                            ] ,
                            'size' => 15
                        ]
                    ],
                    'keywordCnt' => [
                        'terms' => [
                            'field' => 'keyword_list.keyword' ,
                            'order' => [
                                '_count' => 'desc'
                            ] ,
                            'size' => 20
                        ]
                    ],
                    'docStat' => [
                        'terms' => [
                            'field' => 'year' ,
                            'order' => [
                                '_key' => 'asc'
                            ] ,
                            'size' => 200
                        ] ,
                        'aggs' => [
                            'citedPerYear' => [
                                'sum' => [
                                    'field' => 'citation_relate_count'
                                ]
                            ]
                        ]
                    ],
                    'citedCnt' => [
                        'filter' => [
                            'range' => [
                                'citation_relate_count' => [
                                    'gte' => 1
                                ]
                            ]
                        ] ,
                        'aggs' => [
                            'totalCitationCnt' => [
                                'sum' => [
                                    'field' => 'citation_relate_count'
                                ]
                            ] ,
                            'maxCitation' => [
                                'max' => [
                                    'field' => 'citation_relate_count'
                                ]
                            ] ,
                            'citedAuthorCnt' => [
                                'cardinality' => [
                                    'field' => 'author_list.keyword'
                                ]
                            ]
                        ]
                    ],
                    'successCopOrg' => [
                        'filter' => [
                            'range' => [
                                'organization_count' => [
                                    'gte' => 1
                                ]
                            ]
                        ] ,
                        'aggs' => [
                            'corOrgCnt' => [
                                'cardinality' => [
                                    'field' => 'organization_parsed.keyword'
                                ]
                            ]
                        ]
                    ],
                    'successCopAuthor' => [
                        'filter' => [
                            'range' => [
                                'author_count' => [
                                    'gt' => 1
                                ]
                            ]
                        ] ,
                        'aggs' => [
                            'corAuthorCnt' => [
                                'cardinality' => [
                                    'field' => 'author_list.keyword'
                                ]
                            ]
                        ]
                    ],
                    'totalAuthorCnt' => [
                        'cardinality' => [
                            'field' => 'author_list.keyword' ,
                            'precision_threshold' => 1000
                        ]
                    ],
                    'subjectTop' => [
                        'terms' => [
                            'field' => 'subject_top_list.keyword' ,
                            'order' => [
                                '_count' => 'desc'
                            ],
                            'size' => 20
                        ] ,
                    ],
                    'subjectSub' => [
                        'terms' => [
                            'field' => 'subject_sub_list.keyword' ,
                            'order' => [
                                '_count' => 'desc'
                            ],
                            'size' => 20
                        ] ,
                    ]
                ] ,
                'sort' => [
                    [
                        'year' => [
                            'order' => 'desc'
                        ]
                    ]
                ]
            ]
        ];

        $client = $this->getEsClient();
        return $client->search(
            $params
        );
    }

    
    /**
     * 搜索疾病提示（本科室下搜索）
     *
     * @param  string $disease  疾病名称
     * @return Json
     */
    public function searchDisease():Json
    {
        $department  = Request::param('department')   ?? '';
        $disease     = Request::param('disease')      ?? '';
        if( ! $disease || ! $department) {
            return $this->_json_error('请求参数错误！');
        }

        $diseaseList = CdssXyDisease::field('name')->where('department_1' , $department)->where('name' , 'like' , "%$disease%")->whereOr('alias' , 'like' , "%$disease%")->select()->toArray();
        if(empty($disease)) {
            $diseaseList = [];
        }
        return $this->_json_succ(
            $diseaseList
        );
    }


    /**
     * 全部文献（相关推荐底部）
     */
    public function allDocument()
    {
        $page   = Request::param('page')   ?? 1;
        $limit  = ($page - 1) * $this->pagesize;
        $tag    = Request::param('tag')    ?? '';
        $values = Request::param('values') ?? '三明';
        if( ! $values) {
            return $this->_json_error('请求参数有误！');
        }

        switch($tag) {
            /**
             * 学科渗透
             */
            case "subject_infiltration":
                $field = 'subject_top_list.keyword';
                break;
            /**
             * 研究主题
             */
            case "research_topic":
                $field = 'subject_top_list.keyword';
                break;
            /**
             * 热门机构
             */
            case "hot_body":
                $field = 'organization_parsed.keyword';
                break;
            /**
             * 相关学者
             */
            case "relevant_scholars":
                $field = 'author_list.keyword';
                break;
            default:
                $field = 'title';
                break;
        }

        $query = [];

        if(stripos($values , ',') !== false) {
            $valuesArr = explode(',' , $values);
            foreach ($valuesArr as $value) {
                if('relevant_scholars' === $tag) {
                    $valuesArr = explode('-', $value);
                    $value = $valuesArr[0];
                }
                $query['bool']['must'][] = [
                    'match' => [
                        $field => $value
                    ]
                ];
            }
        } else {
            $query['bool']['must'][] = [
                'match' => [
                    $field => $values
                ]
            ];
        }

        $params = [
            'index' => $this->currentLanguage() ,
            'body'  => [
                'from'  => $limit,
                'size'  => $this->pagesize,
                'query' => $query,
                'sort'  => [
                    [
                        'year' => [
                            'order' => 'desc'
                        ]
                    ]
                ]
            ]
        ];

        $client = $this->getEsClient();
        $result = $client->search(
            $params
        );

        $total     = $result['hits']['total'];
        $totalPage = ceil($total / $this->pagesize);
        $hits      = $result['hits']['hits'];
        $data      = array_column($hits, '_source');

        return $this->_json_succ(
            [
                'total_page' => $totalPage ,
                'total'      => $total,
                'list'       => $data
            ]
        );
    }

}
