package com.xueyi.system.pass.controller.api;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.BulkRequest;
import co.elastic.clients.elasticsearch.core.BulkResponse;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.SearchTemplateResponse;
import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.TotalHits;
import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation;
import co.elastic.clients.json.JsonData;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xueyi.common.core.constant.basic.SecurityConstants;
import com.xueyi.common.core.web.result.AjaxResult;
import com.xueyi.common.web.annotation.TenantIgnore;
import com.xueyi.system.api.device.domain.vo.DeviceTenantSourceMergeVo;
import com.xueyi.system.api.pass.domain.dto.DmRecognizedMultiRecordsDto;
import com.xueyi.system.api.pass.domain.dto.DmRecognizedRecordsDto;
import com.xueyi.system.api.pass.domain.po.DmRecognizedRecordsPo;
import com.xueyi.system.api.pass.feign.RemoteRecognizedRecordsService;
import com.xueyi.system.pass.mapper.DmRecognizedRecordsMapper;
import com.xueyi.system.pass.service.impl.DmRecognizedRecordsServiceImpl;
import com.xueyi.system.resource.controller.api.BaseApiController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 人员识别管理 业务处理
 *
 * @author xueyi
 */
@RestController
@RequestMapping("/pass/api")
public class DmRecognizedRecordsApiController extends BaseApiController {
    private static final Logger log = LoggerFactory.getLogger(DmRecognizedRecordsApiController.class);
    @Autowired
    private RemoteRecognizedRecordsService recognizedRecordsFeign;

    @Autowired
    private DmRecognizedRecordsServiceImpl recognizedRecordsService;

    @ResponseBody
    @PostMapping(value = "/upload-pass", produces = "application/json;charset=UTF-8")
    public JSONObject upload(@RequestBody DmRecognizedRecordsDto recognizedRecordsDto) {
        log.info("upload-pass devId={}", recognizedRecordsDto.getDevId());
        DeviceTenantSourceMergeVo vo = super.getDeviceTenantSourceMergeVo(recognizedRecordsDto.getDevId());


        return recognizedRecordsFeign.uploadPass(recognizedRecordsDto, vo.getTenantId(), vo.getSourceSlave(), SecurityConstants.INNER);
    }

    @ResponseBody
    @PostMapping(value = "/upload-multi-pass", produces = "application/json;charset=UTF-8")
    public JSONObject uploads(@RequestBody DmRecognizedMultiRecordsDto recognizedMultiRecordsDto) {
        log.info("upload-multi-pass devId={}", recognizedMultiRecordsDto.getDevId());
        DeviceTenantSourceMergeVo vo = super.getDeviceTenantSourceMergeVo(recognizedMultiRecordsDto.getDevId());
        if (recognizedMultiRecordsDto.getRecords().size() > 0)
            recognizedRecordsService.setRedisRecognizedCount(recognizedMultiRecordsDto.getRecords().size());

        return recognizedRecordsFeign.uploadMultiPass(recognizedMultiRecordsDto, vo.getTenantId(), vo.getSourceSlave(), SecurityConstants.INNER);
    }

    @Autowired
    private DmRecognizedRecordsMapper recordsMapper;

//    @Autowired
//    private RecognizedRecordsRepository recordsRepository;

//    @Autowired
//    private RecognizedRecordsRepository recordsRepository;

    @Autowired
    private ElasticsearchClient esClient;

    @GetMapping("/syncEs")
    @TenantIgnore(tenantLine = true)
    public AjaxResult sync(@RequestHeader(value = SecurityConstants.SOURCE_NAME, defaultValue = "salve") String sourceName, @RequestHeader(value = SecurityConstants.ENTERPRISE_ID, defaultValue = "-1") Long enterpriseId, @RequestHeader(value = SecurityConstants.FROM_SOURCE, defaultValue = SecurityConstants.INNER) String source) {
        List<DmRecognizedRecordsPo> lists = recordsMapper.selectList(new QueryWrapper<>());

        BulkRequest.Builder br = new BulkRequest.Builder();

        System.err.println(lists.get(0));
        for (int j = 0; j < lists.size(); j++) {
            int finalJ = j;
            br.operations(op -> op
                    .index(idx -> {

                        return idx
                                .index("saas-recognized-records")
                                .id(lists.get(finalJ).getId().toString())
                                .document(lists.get(finalJ));
                            }
                    )
            );
        }

        try {
            BulkResponse result = esClient.bulk(br.build());
            if (result.errors()) {
                log.error("Bulk had errors");
                for (BulkResponseItem item : result.items()) {
                    if (item.error() != null) {
                        log.error(item.error().reason());
                    }
                }
            }
        } catch (IOException e) {
            log.error("sync error:{}", e.getMessage());
            throw new RuntimeException(e);
        }

//        lists.stream().forEach(f->recordsRepository.save((EsRecognizedRecordsPo) f));
        return AjaxResult.success();
    }




    @GetMapping("/queryEs")
    @TenantIgnore(tenantLine = true)
    public AjaxResult queryEs(@RequestHeader(value = SecurityConstants.SOURCE_NAME, defaultValue = "salve") String sourceName, @RequestHeader(value = SecurityConstants.ENTERPRISE_ID, defaultValue = "-1") Long enterpriseId, @RequestHeader(value = SecurityConstants.FROM_SOURCE, defaultValue = SecurityConstants.INNER) String source, @RequestBody JSONObject params) {
        DmRecognizedRecordsPo ee = new DmRecognizedRecordsPo();
        System.err.println(ee.getClass().getName());
        System.err.println(ee.getClass().getSimpleName());

        SearchTemplateResponse<DmRecognizedRecordsPo> response = null;
        SearchResponse<DmRecognizedRecordsPo> response2 = null;
        Query byName = MatchQuery.of(m -> m
                .field("userName")
                .query(params.getString("userName"))
        )._toQuery();

// Search by max price
        Query byDeptId = MatchQuery.of(r -> r
                .field("deptId")
                .query(params.getString("deptId"))
//                .gte(JsonData.of("1676567054881718273"))
        )._toQuery();
        try {
            response2 = esClient.search(s -> s
                            .index("saas-recognized-records")
                            .query(q -> q
                                    .bool(b -> b.must(byName).must(byDeptId))
                            ).from(params.getInteger("from")).size(params.getInteger("size")),
                    DmRecognizedRecordsPo.class
            );
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        TotalHits total = response2.hits().total();
        boolean isExactResult = total.relation() == TotalHitsRelation.Eq;

        if (isExactResult) {
            log.info("There are " + total.value() + " results");
        } else {
            log.info("There are more than " + total.value() + " results");
        }
        List<DmRecognizedRecordsPo> products2 = response2.hits().hits().stream().map(f->f.source()).collect(
                Collectors.toList()
        );

        List<Hit<DmRecognizedRecordsPo>> hits = response2.hits().hits();
        for (Hit<DmRecognizedRecordsPo> hit: hits) {
            DmRecognizedRecordsPo product = hit.source();
            log.info("Found product " + product.getDevId() + ", score " + hit.score());
        }
        try {
            response = esClient.searchTemplate(r -> r
                            .index("saas-recognized-records")
                            .id("records-search-template")
                            .params("query_string", JsonData.of(params.getString("userName")))
                            .params("from", JsonData.of(params.getInteger("from")))
                            .params("size", JsonData.of(params.getInteger("size")))
                            ,
                    DmRecognizedRecordsPo.class
            );
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        List<Hit<DmRecognizedRecordsPo>> hits2 = response.hits().hits();
        List<DmRecognizedRecordsPo> products = response.hits().hits().stream().map(f->f.source()).collect(
                Collectors.toList()
        );


//        lists.stream().forEach(f->recordsRepository.save((EsRecognizedRecordsPo) f));
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("data", products);
        jsonObject.put("data2", products2);

        return AjaxResult.success(jsonObject);
    }


}
