package com.yanzhu.module.ai.framework.ai.core.webserch.bocha;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import com.yanzhu.framework.common.pojo.CommonResult;
import com.yanzhu.module.ai.framework.ai.core.webserch.AiWebSearchClient;
import com.yanzhu.module.ai.framework.ai.core.webserch.AiWebSearchRequest;
import com.yanzhu.module.ai.framework.ai.core.webserch.AiWebSearchResponse;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import java.util.Collections;

import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;

import static com.yanzhu.framework.common.util.collection.CollectionUtils.convertList;

/**
 * 博查 {@link AiWebSearchClient} 实现类
 *
 * @see <a href="https://open.bochaai.com/overview">博查 AI 开放平台</a>
 *
 * @author 研筑科技
 */
@Slf4j
public class AiBoChaWebSearchClient implements AiWebSearchClient {

    public static final String BASE_URL = "https://api.bochaai.com";
    private static final String AUTHORIZATION_HEADER = "Authorization";
    private static final String BEARER_PREFIX = "Bearer ";

    private final RestTemplate restTemplate;
    private final String apiKey;

    public AiBoChaWebSearchClient(String apiKey) {
        this.restTemplate = new RestTemplate();
        this.apiKey = apiKey;
    }

    @Override
    public AiWebSearchResponse search(AiWebSearchRequest request) {
        // 转换请求参数
        WebSearchRequest webSearchRequest = new WebSearchRequest(
                request.getQuery(),
                request.getSummary(),
                request.getCount()
        );
        
        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add(AUTHORIZATION_HEADER, BEARER_PREFIX + apiKey);
        
        HttpEntity<WebSearchRequest> entity = new HttpEntity<>(webSearchRequest, headers);
        
        try {
            // 调用博查 API
            ResponseEntity<CommonResult<WebSearchResponse>> response = restTemplate.exchange(
                    BASE_URL + "/v1/web-search",
                    HttpMethod.POST,
                    entity,
                    new ParameterizedTypeReference<CommonResult<WebSearchResponse>>() {}
            );
            
            if (response.getStatusCode().series() != HttpStatus.Series.SUCCESSFUL) {
                log.error("[AiBoChaWebSearchClient] 调用失败！请求参数:[{}]，响应状态码: [{}]", webSearchRequest, response.getStatusCode());
                throw new IllegalStateException("[AiBoChaWebSearchClient] 调用失败！");
            }
            
            CommonResult<WebSearchResponse> commonResult = response.getBody();
            if (commonResult == null) {
                throw new IllegalStateException("[search][搜索结果为空]");
            }
            if (commonResult.getData() == null) {
                throw new IllegalStateException(String.format("[search][搜索失败，code = %s, msg = %s]",
                        commonResult.getCode(), commonResult.getMsg()));
            }
            WebSearchResponse data = commonResult.getData();
            
            // 转换结果
            AiWebSearchResponse result = new AiWebSearchResponse();
            if (data.getWebPages() == null || CollUtil.isEmpty(data.getWebPages().getValue())) {
                return result.setTotal(0L).setLists(Collections.emptyList());
            }
            return result.setTotal(data.getWebPages().getTotalEstimatedMatches())
                    .setLists(convertList(data.getWebPages().getValue(), page -> new AiWebSearchResponse.WebPage()
                            .setName(page.getSiteName()).setIcon(page.getSiteIcon())
                            .setTitle(page.getName()).setUrl(page.getUrl())
                            .setSnippet(page.getSnippet()).setSummary(page.getSummary())));
        } catch (Exception e) {
            log.error("[AiBoChaWebSearchClient] 调用异常！请求参数:[{}]", webSearchRequest, e);
            throw new RuntimeException("[AiBoChaWebSearchClient] 调用失败！", e);
        }
    }

    /**
     * 网页搜索请求参数
     */
    @JsonInclude(value = JsonInclude.Include.NON_NULL)
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class WebSearchRequest {
        private String query;
        private Boolean summary;
        private Integer count;

        public WebSearchRequest(String query) {
            Assert.notBlank(query, "query 不能为空");
            this.query = query;
        }
    }

    /**
     * 网页搜索响应
     */
    @JsonInclude(value = JsonInclude.Include.NON_NULL)
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class WebSearchResponse {
        private WebSearchWebPages webPages;
    }

    /**
     * 网页搜索结果
     */
    @JsonInclude(value = JsonInclude.Include.NON_NULL)
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class WebSearchWebPages {
        private String webSearchUrl;
        private Long totalEstimatedMatches;
        private List<WebPageValue> value;
        private Boolean someResultsRemoved;

        /**
         * 网页结果值
         */
        @JsonInclude(value = JsonInclude.Include.NON_NULL)
        @Data
        @NoArgsConstructor
        @AllArgsConstructor
        public static class WebPageValue {
            private String id;
            private String name;
            private String url;
            private String displayUrl;
            private String snippet;
            private String summary;
            private String siteName;
            private String siteIcon;
            private String datePublished;
            private String dateLastCrawled;
            private String cachedPageUrl;
            private String language;
            private Boolean isFamilyFriendly;
            private Boolean isNavigational;
        }
    }

}
