package utils

import (
	"crypto/tls"
	"fmt"
	"io"
	"net"
	"net/http"
	"net/url"
	"regexp"
	"strings"
	"time"
)

// HTTPClient HTTP客户端工具
type HTTPClient struct {
	client *http.Client
}

// NewHTTPClient 创建HTTP客户端
func NewHTTPClient(timeout time.Duration) *HTTPClient {
	transport := &http.Transport{
		TLSClientConfig:       &tls.Config{InsecureSkipVerify: true},
		MaxIdleConns:          100,
		MaxIdleConnsPerHost:   10,
		IdleConnTimeout:       90 * time.Second,
		TLSHandshakeTimeout:  10 * time.Second,
		ResponseHeaderTimeout: timeout,
		DialContext: (&net.Dialer{
			Timeout:   10 * time.Second,
			KeepAlive: 30 * time.Second,
		}).DialContext,
	}

	return &HTTPClient{
		client: &http.Client{
			Timeout:   timeout,
			Transport: transport,
			CheckRedirect: func(req *http.Request, via []*http.Request) error {
				if len(via) >= 10 {
					return fmt.Errorf("too many redirects")
				}
				return nil
			},
		},
	}
}

// CheckResult 检查结果
type CheckResult struct {
	StatusCode int
	Latency    time.Duration
	Title      string
	Favicon    string
	Error      error
}

// CheckWebsiteStatus 轻量级状态检测（不读取页面内容）
func (c *HTTPClient) CheckWebsiteStatus(targetURL string) CheckResult {
	result := CheckResult{}

	start := time.Now()

	req, err := http.NewRequest("GET", targetURL, nil)
	if err != nil {
		result.Error = err
		return result
	}

	req.Header.Set("User-Agent", "MengYaPing/1.0 (Website Monitor)")
	req.Header.Set("Accept", "*/*")
	req.Header.Set("Connection", "close")

	resp, err := c.client.Do(req)
	if err != nil {
		result.Error = err
		result.Latency = time.Since(start)
		return result
	}
	defer resp.Body.Close()

	result.Latency = time.Since(start)
	result.StatusCode = resp.StatusCode

	// 丢弃少量 body 以便连接正确释放
	io.Copy(io.Discard, io.LimitReader(resp.Body, 4096))

	return result
}

// CheckWebsite 完整检查（读取页面提取标题等元数据）
func (c *HTTPClient) CheckWebsite(targetURL string) CheckResult {
	result := CheckResult{}

	start := time.Now()

	req, err := http.NewRequest("GET", targetURL, nil)
	if err != nil {
		result.Error = err
		return result
	}

	req.Header.Set("User-Agent", "MengYaPing/1.0 (Website Monitor)")
	req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")

	resp, err := c.client.Do(req)
	if err != nil {
		result.Error = err
		result.Latency = time.Since(start)
		return result
	}
	defer resp.Body.Close()

	result.Latency = time.Since(start)
	result.StatusCode = resp.StatusCode

	body, err := io.ReadAll(io.LimitReader(resp.Body, 1024*100))
	if err == nil {
		result.Title = extractTitle(string(body))
		result.Favicon = extractFavicon(string(body), targetURL)
	}

	return result
}

// extractTitle 提取网页标题
func extractTitle(html string) string {
	re := regexp.MustCompile(`(?i)<title[^>]*>([^<]+)</title>`)
	matches := re.FindStringSubmatch(html)
	if len(matches) > 1 {
		return strings.TrimSpace(matches[1])
	}
	return ""
}

// extractFavicon 提取Favicon
func extractFavicon(html string, baseURL string) string {
	parsedURL, err := url.Parse(baseURL)
	if err != nil {
		return ""
	}

	patterns := []string{
		`(?i)<link[^>]*rel=["'](?:shortcut )?icon["'][^>]*href=["']([^"']+)["']`,
		`(?i)<link[^>]*href=["']([^"']+)["'][^>]*rel=["'](?:shortcut )?icon["']`,
		`(?i)<link[^>]*rel=["']apple-touch-icon["'][^>]*href=["']([^"']+)["']`,
	}

	for _, pattern := range patterns {
		re := regexp.MustCompile(pattern)
		matches := re.FindStringSubmatch(html)
		if len(matches) > 1 {
			faviconURL := matches[1]
			return resolveURL(parsedURL, faviconURL)
		}
	}

	return fmt.Sprintf("%s://%s/favicon.ico", parsedURL.Scheme, parsedURL.Host)
}

// resolveURL 解析相对URL
func resolveURL(base *url.URL, ref string) string {
	refURL, err := url.Parse(ref)
	if err != nil {
		return ref
	}
	return base.ResolveReference(refURL).String()
}

// IsSuccessStatus 判断是否为成功状态码
func IsSuccessStatus(statusCode int) bool {
	return statusCode >= 200 && statusCode < 400
}
