package com.infoepoch.pms.agent.platform.agent.adapter.out.tool;

import com.infoepoch.pms.agent.platform.agent.adapter.out.tool.support.ChatbotBuiltInToolType;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.function.FunctionToolCallback;
import org.springframework.ai.tool.metadata.ToolMetadata;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 聊天机器人网页抓取工具。
 */
@Component
public class WebFetchTool {

    private static final int MAX_FETCH_CONTENT_LENGTH = 6000;
    private static final Pattern TITLE_PATTERN = Pattern.compile("(?is)<title[^>]*>(.*?)</title>");

    private final HttpClient httpClient;

    public WebFetchTool() {
        this.httpClient = HttpClient.newBuilder()
                .followRedirects(HttpClient.Redirect.NORMAL)
                .connectTimeout(Duration.ofSeconds(10))
                .build();
    }

    /**
     * 创建工具回调。
     *
     * @return 工具回调
     */
    public ToolCallback createToolCallback() {
        return FunctionToolCallback
                .builder(ChatbotBuiltInToolType.WEB_FETCH.getKey(), (WebFetchRequest request) -> fetchWebPage(request.url()))
                .description(ChatbotBuiltInToolType.WEB_FETCH.getDescription())
                .inputType(WebFetchRequest.class)
                .toolMetadata(ToolMetadata.builder().returnDirect(false).build())
                .build();
    }

    private WebFetchResponse fetchWebPage(String url) {
        if (!StringUtils.hasText(url)) {
            throw new IllegalArgumentException("URL cannot be empty or null");
        }
        try {
            HttpRequest request = HttpRequest.newBuilder(URI.create(url.trim()))
                    .timeout(Duration.ofSeconds(20))
                    .GET()
                    .build();
            HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
            String rawHtml = Optional.ofNullable(response.body()).orElse("");
            String normalizedContent = normalizeFetchedContent(rawHtml);
            boolean truncated = normalizedContent.length() > MAX_FETCH_CONTENT_LENGTH;

            return new WebFetchResponse(
                    response.uri().toString(),
                    response.statusCode(),
                    response.headers().firstValue("Content-Type").orElse(""),
                    extractTitle(rawHtml),
                    truncated ? normalizedContent.substring(0, MAX_FETCH_CONTENT_LENGTH) : normalizedContent,
                    truncated
            );
        }
        catch (IOException | IllegalArgumentException ex) {
            throw new IllegalStateException("抓取网页内容失败: " + url, ex);
        }
        catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
            throw new IllegalStateException("抓取网页内容失败: " + url, ex);
        }
    }

    private String extractTitle(String rawHtml) {
        if (!StringUtils.hasText(rawHtml)) {
            return null;
        }
        Matcher matcher = TITLE_PATTERN.matcher(rawHtml);
        if (!matcher.find()) {
            return null;
        }
        String normalizedTitle = matcher.group(1)
                .replaceAll("\\s+", " ")
                .trim();
        return normalizedTitle.isEmpty() ? null : normalizedTitle;
    }

    private String normalizeFetchedContent(String rawContent) {
        if (!StringUtils.hasText(rawContent)) {
            return "";
        }
        return rawContent
                .replaceAll("(?is)<script.*?>.*?</script>", " ")
                .replaceAll("(?is)<style.*?>.*?</style>", " ")
                .replaceAll("(?is)<head.*?>.*?</head>", " ")
                .replaceAll("(?is)<[^>]+>", " ")
                .replaceAll("&nbsp;", " ")
                .replaceAll("\\s+", " ")
                .trim();
    }

    /**
     * 网页抓取请求。
     *
     * @param url 目标地址
     */
    public record WebFetchRequest(String url) {
    }

    /**
     * 网页抓取结果。
     *
     * @param finalUrl   实际抓取地址
     * @param statusCode HTTP 状态码
     * @param contentType 内容类型
     * @param title      网页标题
     * @param content    提取后的正文
     * @param truncated  正文是否被截断
     */
    public record WebFetchResponse(String finalUrl,
                                   int statusCode,
                                   String contentType,
                                   String title,
                                   String content,
                                   boolean truncated) {
    }
}
