package com.yeejoin.amos.boot.module.common.biz.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.module.common.api.constant.TZSCommonConstant;
import com.yeejoin.amos.component.feign.utils.FeignUtil;
import com.yeejoin.amos.feign.privilege.Privilege;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.feign.privilege.model.CompanyModel;
import lombok.RequiredArgsConstructor;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.io.IOException;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class UserOperateLogServiceImpl {

    private final RestHighLevelClient restHighLevelClient;

    public Page<JSONObject> page(int current, int size, JSONObject params) {
        Page<JSONObject> result = new Page<>(current, size);
        SearchRequest request = new SearchRequest();
        request.indices(TZSCommonConstant.ES_INDEX_NAME_USER_OPERATE_LOG);
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.trackTotalHits(true);
        BoolQueryBuilder boolMust = QueryBuilders.boolQuery();

        // 业务方法定义精确查询
        if (!ObjectUtils.isEmpty(params.getString("methodName"))) {
            BoolQueryBuilder pBuilder = QueryBuilders.boolQuery();
            pBuilder.must(QueryBuilders.termQuery("methodName.keyword", params.getString("methodName")));
            boolMust.must(pBuilder);
        }
        // 业务方法名称精确查询
        if (!ObjectUtils.isEmpty(params.getString("methodLabel"))) {
            BoolQueryBuilder pBuilder = QueryBuilders.boolQuery();
            pBuilder.must(QueryBuilders.termQuery("methodLabel.keyword", params.getString("methodLabel")));
            boolMust.must(pBuilder);
        }

        // 入参关键字模糊查询
        if (!ObjectUtils.isEmpty(params.getString("params"))) {
            BoolQueryBuilder pBuilder = QueryBuilders.boolQuery();
            pBuilder.must(QueryBuilders.termQuery("params.keyword", params.getString("params")));
            boolMust.must(pBuilder);
        }

        // 出参关键字查询
        if (!ObjectUtils.isEmpty(params.getString("result"))) {
            BoolQueryBuilder pBuilder = QueryBuilders.boolQuery();
            pBuilder.must(QueryBuilders.termQuery("result.keyword", params.getString("result")));
            boolMust.must(pBuilder);
        }

        // 操作人账号关键字查询
        if (!ObjectUtils.isEmpty(params.getString("loginId"))) {
            BoolQueryBuilder pBuilder = QueryBuilders.boolQuery();
            pBuilder.must(QueryBuilders.termQuery("loginId", params.getString("loginId")));
            boolMust.must(pBuilder);
        }

        // 操作人userId关键字查询
        if (!ObjectUtils.isEmpty(params.getString("userId"))) {
            BoolQueryBuilder pBuilder = QueryBuilders.boolQuery();
            pBuilder.must(QueryBuilders.termQuery("userId", params.getString("userId")));
            boolMust.must(pBuilder);
        }
        builder.query(boolMust);
        builder.sort("createDate", SortOrder.DESC);
        builder.from((current - 1) * size);
        builder.size(size);
        request.source(builder);
        List<JSONObject> list = new LinkedList<>();
        long totle = 0;
        try {
            Set<String> userIds = new HashSet<>();
            SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
            for (SearchHit hit : response.getHits().getHits()) {
                System.out.println(hit);
                JSONObject jsonObject = (JSONObject) JSONObject.toJSON(hit);
                JSONObject dto2 = jsonObject.getJSONObject("sourceAsMap");
                userIds.add(dto2.getString("userId"));
                list.add(dto2);
            }
            // 填充操作人名称、填充操作人单位
            this.fillingUserInfo(list, userIds);
            totle = Objects.requireNonNull(response.getInternalResponse().hits().getTotalHits()).value;
            result.setRecords(list);
            result.setTotal(totle);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return result;
    }

    private void fillingUserInfo(List<JSONObject> list, Set<String> userIds) {
        List<AgencyUserModel> userModels = FeignUtil.remoteCall(() -> Privilege.agencyUserClient.queryByIds(String.join(",", userIds), true));
        Map<String, AgencyUserModel> userIdUserMap = userModels.stream().collect(Collectors.toMap(AgencyUserModel::getUserId, Function.identity()));
        list.forEach(item -> {
            item.put("realName", Optional.ofNullable(userIdUserMap.get(item.getString("userId"))).map(AgencyUserModel::getRealName).orElse(""));
            item.put("companyName", Optional.ofNullable(userIdUserMap.get(item.getString("userId"))).map(AgencyUserModel::getOrgNamesWithoutRole).orElse(""));
            item.remove("token");
        });
    }

}
