package com.bawei.mall.search.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.bawei.common.core.domain.R;
import com.bawei.common.core.exception.ServiceException;
import com.bawei.common.core.utils.StringUtils;
import com.bawei.mall.product.domain.reponse.ProductInfoResponse;
import com.bawei.mall.product.remote.RemoteProductInfo;
import com.bawei.mall.search.domain.request.SearchReq;
import com.bawei.mall.search.es.instance.EsInstance;
import com.bawei.mall.search.es.service.EsDataService;
import com.bawei.mall.search.service.SearchService;
import com.bawei.mall.search.utils.SearchResultUtils;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author DongZl
 * @description: 搜索业务实现类
 * @Date 2022-10-21 下午 02:53
 */
@Service
public class SearchServiceImpl implements SearchService {

    private static final Logger log = LoggerFactory.getLogger(SearchServiceImpl.class);

    @Autowired
    private RemoteProductInfo remoteProductInfo;

    @Autowired
    private EsDataService esDataService;

    @Autowired
    private EsInstance esInstance;

    @Override
    public void syncProductInfo (Long productId) {
        R<ProductInfoResponse> resultInfo = remoteProductInfo.getResultInfo(productId);
        esDataService.insertOrUpdate("shop_item", resultInfo.getData());
        log.info("商品:[{}]同步完成", productId);
    }

    /**
     * 搜索
     *
     * @param searchReq
     */
    @Override
    public void search (SearchReq searchReq) {
        if (StringUtils.isEmpty(searchReq.getKeyWord())){
            throw new ServiceException("搜索参数不可以为空");
        }

        SearchRequest searchRequest = esInstance.SearchRequestBuilder("shop_item");
        SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.searchSource();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        // 商品名称搜索
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery(
                "name", searchReq.getKeyWord()
        );
        boolQueryBuilder.must(matchQueryBuilder);
        // 分页
        searchSourceBuilder.from((searchReq.getPageNum() - 1) * searchReq.getPageSize());
        searchSourceBuilder.size(searchReq.getPageSize());

        searchSourceBuilder.query(boolQueryBuilder);

        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("name");
        highlightBuilder.preTags("<span style='color:red'>");
        highlightBuilder.postTags("</span>");
        searchSourceBuilder.highlighter(highlightBuilder);
        searchRequest.source(searchSourceBuilder);
        try {
            SearchResponse searchResponse = esInstance.getClient().search(searchRequest, RequestOptions.DEFAULT);
            SearchHits searchResponseHits = searchResponse.getHits();
            TotalHits totalHits = searchResponseHits.getTotalHits();
            // 若未查询到数量结果，直接进行返回
            if (totalHits.value != 0){
                SearchResultUtils.setTotal(totalHits.value);
            }
            List<ProductInfoResponse> productInfoResponseList = new ArrayList<>();
            SearchHit[] searchHits = searchResponseHits.getHits();
            for (SearchHit searchHit : searchHits) {
                // 源数据
                String sourceAsString = searchHit.getSourceAsString();
                ProductInfoResponse productInfoResponse =
                        JSONObject.parseObject(sourceAsString, ProductInfoResponse.class);
                // 高亮
                Map<String, HighlightField> highlightFields =
                        searchHit.getHighlightFields();
                if (highlightFields != null){
                    HighlightField highlightField = highlightFields.get("name");
                    if (highlightField != null){
                        // 拼装
                        Text[] fragments = highlightField.getFragments();
                        StringBuilder sb = new StringBuilder();
                        for (Text fragment : fragments) {
                            sb.append(fragment);
                        }
                        productInfoResponse.setName(sb.toString());
                    }
                }
                productInfoResponseList.add(productInfoResponse);
            }
            SearchResultUtils.setList(productInfoResponseList);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
