<?php

namespace App\Services\goods;

use Api\PhpUtils\Common\BaseConvert;
use Api\PhpUtils\Common\IP;
use Api\PhpUtils\Elastic\ElasticUtil;
use App\Models\goods\mysql\GoodsSku;

class ElasticGoodService
{
    const INDEX = "bp_goods";

    const SORT_TYPE_COMPREHENSIVE = 0;
    const SORT_TYPE_DISTANCE = 1;
    const SORT_TYPE_SALES = 2;
    const SORT_TYPE_PRICE = 3;

    //添加生活号id，这里的生活号id发的商品，es查不出来
    const TEST_LIFE_ACCOUNT_ID = [];
    //公司内网wifi ip
    const WIFI_IPS = ['123.103.40.112','123.103.40.113','123.103.40.114','123.103.40.115','123.103.40.116','123.103.40.117'];

    public static function createIndex()
    {
        $elasticClient = ElasticUtil::getInstance();
        $data = [
            "settings" => [
                "analysis" => [
                    "analyzer" => [
                        "default" => [
                            "type" => "ik_max_word",
                        ]
                    ]
                ]
            ],
            'mappings' => [
                'properties' => [
                    'goods_name' => [
                        'type' => 'text',
                        'analyzer' => 'ik_max_word',
                    ],
                    'desc' => [
                        'type' => 'text',
                        'analyzer' => 'ik_max_word',
                    ],
                    'category_1_name' => [
                        'type' => 'text',
                        'analyzer' => 'ik_max_word',
                    ],
                    'category_2_name' => [
                        'type' => 'text',
                        'analyzer' => 'ik_max_word',
                    ],
                    'life_account_name' => [
                        'type' => 'text',
                        'analyzer' => 'ik_max_word',
                    ],
                    'shop_name' => [
                        'type' => 'text',
                        'analyzer' => 'ik_max_word',
                    ],
                    'shop_location' => [
                        'type' => 'geo_point',
                    ],
                ]
            ]
        ];
        return $elasticClient->createIndex(self::INDEX, $data);
    }

    /**
     * 删除
     */
    public static function deleteIndex(): void
    {
        $elasticClient = ElasticUtil::getInstance();

        $res = $elasticClient->deleteIndex(self::INDEX);
        var_dump($res);
    }

    /**
     * 写入 es 一条数据
     * @param $data
     * @param $id
     * @return array|callable
     */
    public static function indexDoc($id, $data)
    {
        $elasticClient = ElasticUtil::getInstance();
        return $elasticClient->indexDoc(self::INDEX, $data, $id);
    }

    /**
     * 修改 es 一条数据
     * @param $id
     * @param $data
     * @return array|callable
     */
    public static function updateDoc($id, $data)
    {
        $elasticClient = ElasticUtil::getInstance();
        return $elasticClient->updateDoc(self::INDEX, $id, $data);
    }

    public static function bulk($index)
    {
        $elasticClient = ElasticUtil::getInstance();

        $data = [
            ['index' => ['_index' => $index]],
            ['test_field' => '公安部：各地校车将享最高路权'],
            ['index' => ['_index' => $index]],
            ['test_field' => '中韩渔警冲突调查：韩警平均每天扣1艘中国渔船'],
            ['index' => ['_index' => $index]],
            ['test_field' => '中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首'],
        ];
        $res = $elasticClient->bulkIndexDoc($data);
        var_export($res);
    }

    /**
     * @param array $params
     * @return array|object
     */
    public static function searchDoc($params = [])
    {
        $dataSort = self::getSortConditions($params);
        $dataConditions = self::getSearchConditions($params);

        $data = array_merge($dataSort, $dataConditions);
        $elasticClient = ElasticUtil::getInstance();
        $res = $elasticClient->searchDoc(self::INDEX, $data);

        $result = [];
        if (!empty($res["hits"]["total"]["value"])) {
            $result["count"] = $res["hits"]["total"]["value"];
            foreach ($res["hits"]["hits"] as $key => $source) {

                $result["list"][$key]["goods_desc_pic_url_list"] = [];
                if (!empty($source["_source"]["goods_desc_pic_url"])) {
                    $ksyun = GoodsService::getUrlList($source["_source"]["goods_desc_pic_url"], 200, 200);
                    $result["list"][$key]["goods_desc_pic_url_list"] = $ksyun;
                }

                $result["list"][$key]["goods_sku_id"] = $source["_source"]["goods_sku_id"];
                $result["list"][$key]["goods_desc_pic_url"] = $source["_source"]["goods_desc_pic_url"];
                $result["list"][$key]["goods_name"] = $source["_source"]["goods_name"];
                $result["list"][$key]["inventory_rest"] = $source["_source"]["inventory_rest"];
                $result["list"][$key]["total_amount_sold"] = $source["_source"]["total_amount_sold"];
                $result["list"][$key]["original_price"] = $source["_source"]["original_price"];
                $result["list"][$key]["price"] = $source["_source"]["price"];
                $result["list"][$key]["audit_status"] = $source["_source"]["audit_status"];
                $result["list"][$key]["online_status"] = $source["_source"]["online_status"];
                $result["list"][$key]["shop_name"] = $source["_source"]["shop_name"];
                $result["list"][$key]["shop_address"] = $source["_source"]["shop_address"];
                $result["list"][$key]["shop_location"] = $source["_source"]["shop_location"];
                $result["list"][$key]["life_account_id"] = $source["_source"]["life_account_id"];
                $result["list"][$key]["life_account_name"] = $source["_source"]["life_account_name"];
                $result["list"][$key]["life_account_icon"] = $source["_source"]["life_account_icon"];
                $result["list"][$key]["distance"] = empty($source["sort"]) ? "" : round(end($source["sort"]), 2) . "km";
                $result["list"][$key]["update_time"] = $source["_source"]["update_time"];
            }
        }
        //为避免空数据时候返回给前端错误结构
        return $result ? $result : (object)$result;
    }

    /**
     * 排序条件
     * @param array $params
     * @return array
     */
    private static function getSortConditions($params = [])
    {
        // sort_type : 0综合排序，1距离，2销量，3价格
        $sortType = empty($params["sort_type"]) ? self::SORT_TYPE_COMPREHENSIVE : $params["sort_type"];
        $latitude = empty($params["latitude"]) ? "" : $params["latitude"];
        $longitude = empty($params["longitude"]) ? "" : $params["longitude"];

        $subjectName = empty($params["subject_name"]) ? "" : $params["subject_name"];
        $subjectSort = [];
        if ($subjectName == "本周上新") {
            $subjectSort = ["update_time" => "desc"];
        }

        $sortList = [
            ["price_sort" => "asc", "total_amount_sold" => "desc"],
            [],
            ["total_amount_sold" => "desc"],
            ["price_sort" => "asc"],
        ];

        $sortInit = isset($sortList[$sortType]) ? $sortList[$sortType] : $sortList[0];
        $sort = array_merge($sortInit, $subjectSort);
        $data = [
            "sort" => $sort,
        ];

        if (!empty($latitude) && !empty($longitude)) {
            $data["sort"]["_geo_distance"] = [
                "shop_location" => [
                    "lat" => $params["latitude"],
                    "lon" => $params["longitude"],
                ],
                "order" => "asc",
                "unit" => "km",
                "distance_type" => "plane",//更快但精度稍差的 plane 计算方法
            ];
        }
        return $data;
    }

    /**
     * 查询条件
     * @param array $params
     * @param array $data
     * @return array|int[]
     */
    private static function getSearchConditions($params = [])
    {
        $from = empty($params["from"]) ? 1 : (int)$params["from"];
        $size = empty($params["size"]) ? 10 : (int)$params["size"];
        $latitude = empty($params["latitude"]) ? "" : $params["latitude"];
        $longitude = empty($params["longitude"]) ? "" : $params["longitude"];
        $searchContent = empty($params["search_content"]) ? "" : $params["search_content"];
        $subjectName = empty($params["subject_name"]) ? "" : $params["subject_name"];
        $lifeAccountId = empty($params["life_account_id"]) ? "" : $params["life_account_id"];
        $ip = empty($params["ip"]) ? "" : $params["ip"];

        $data = [
            "from" => ($from - 1) * $size,
            "size" => $size,
        ];

        $mustInit = [
            ["term" => ["audit_status" => GoodsSku::STATUS_PASS]],
            ["term" => ["online_status" => GoodsSku::ONLINE_STATUS_ONLINE]],
        ];
        //线上环境，配置不允许发现的生活号发布的商品
        $env = \Yaf\Application::app()->environ();
        if (in_array($env, ['dev'])) {
            if (!empty(self::TEST_LIFE_ACCOUNT_ID) && !in_array($ip, self::WIFI_IPS)) {
                $data["query"]["bool"]["must_not"] = ["terms" => ["life_account_id" => self::TEST_LIFE_ACCOUNT_ID]];
            }
        }
        //gte 是大于等于; gt是大于; lte是小于等于; lt是小于
        $data["query"]["bool"]["filter"][]["range"] = ["inventory_rest" => [["gt" => 0]]];
        //$data["query"]["bool"]["filter"][]["range"] = ["price" => [["gt" => 0]]];
        if (!empty($searchContent) || (!empty($subjectName) && $subjectName != "本周上新")) {
            $multiMatch = [["multi_match" => [
                "query" => $searchContent.$subjectName,
                "fields" => ["goods_name", "category_1_name", "category_2_name", "desc", "life_account_name", "shop_name", "shop_address"],
            ]]];

            $data["query"]["bool"]["must"] = array_merge($mustInit, $multiMatch);
        } else {
            $data["query"]["bool"]["must"] = $mustInit;
        }

        if (!empty($lifeAccountId)) {
            $lifeAccountData = [["term" => ["life_account_id" => $lifeAccountId]]];
            $data["query"]["bool"]["must"] = array_merge($data["query"]["bool"]["must"], $lifeAccountData);
        }

        if (!empty($latitude) && !empty($longitude)) {
            $data["query"]["bool"]["filter"][]["geo_distance"] = [
                "distance" => "50km",
                "shop_location" => [
                    "lat" => $latitude,
                    "lon" => $longitude,
                ]
            ];
        }
        return $data;
    }

    /**
     * id 在es数据里是否存在
     * @param $skuId
     * @return bool
     */
    public static function isHaveById($skuId)
    {
        $data["query"]["bool"]["must"] = [
            ["term" => ["_id" => $skuId]],
        ];

        $elasticClient = ElasticUtil::getInstance();
        $res = $elasticClient->searchDoc(self::INDEX, $data);

        if (!empty($res["hits"]["total"]["value"])) {
            return $res["hits"]["total"]["value"] > 0;
        }
        return false;
    }
}