package service

import (
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net"
	"net/http"
	"strings"
	"time"
)

// IPDetectionService IP 检测服务
type IPDetectionService struct {
	httpClient *http.Client
}

// NewIPDetectionService 创建 IP 检测服务
func NewIPDetectionService() *IPDetectionService {
	return &IPDetectionService{
		httpClient: &http.Client{
			Timeout: 10 * time.Second,
		},
	}
}

// GetPublicIPv4 获取公网 IPv4 地址
func (s *IPDetectionService) GetPublicIPv4() (string, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	req, err := http.NewRequestWithContext(ctx, "GET", "https://api.ipify.org?format=json", nil)
	if err != nil {
		return "", fmt.Errorf("创建请求失败：%w", err)
	}

	resp, err := s.httpClient.Do(req)
	if err != nil {
		return "", fmt.Errorf("请求失败：%w", err)
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("读取响应失败：%w", err)
	}

	var result struct {
		IP string `json:"ip"`
	}

	if err := json.Unmarshal(body, &result); err != nil {
		return "", fmt.Errorf("解析 JSON 失败：%w", err)
	}

	if result.IP == "" {
		return "", fmt.Errorf("未获取到 IPv4 地址")
	}

	return result.IP, nil
}

// GetPublicIPv6 获取公网 IPv6 地址
func (s *IPDetectionService) GetPublicIPv6() (string, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	req, err := http.NewRequestWithContext(ctx, "GET", "https://api64.ipify.org?format=json", nil)
	if err != nil {
		return "", fmt.Errorf("创建请求失败：%w", err)
	}

	resp, err := s.httpClient.Do(req)
	if err != nil {
		return "", fmt.Errorf("请求失败：%w", err)
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("读取响应失败：%w", err)
	}

	var result struct {
		IP string `json:"ip"`
	}

	if err := json.Unmarshal(body, &result); err != nil {
		return "", fmt.Errorf("解析 JSON 失败：%w", err)
	}

	if result.IP == "" {
		return "", fmt.Errorf("未获取到 IPv6 地址")
	}

	// 检查是否是 IPv6 地址（包含冒号）
	if !strings.Contains(result.IP, ":") {
		return "", fmt.Errorf("获取到的不是有效的 IPv6 地址：%s", result.IP)
	}

	return result.IP, nil
}

// GetLocalIPv4 获取本地 IPv4 地址（第一个非回环接口）
func (s *IPDetectionService) GetLocalIPv4() (string, error) {
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		return "", fmt.Errorf("获取网络接口失败：%w", err)
	}

	for _, addr := range addrs {
		// 检查是否为 IP 地址且为 IPv4
		if ipNet, ok := addr.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
			if ipNet.IP.To4() != nil {
				return ipNet.IP.String(), nil
			}
		}
	}

	return "", fmt.Errorf("未找到 IPv4 地址")
}

// GetLocalIPv6 获取本地 IPv6 地址（第一个非回环接口）
func (s *IPDetectionService) GetLocalIPv6() (string, error) {
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		return "", fmt.Errorf("获取网络接口失败：%w", err)
	}

	for _, addr := range addrs {
		if ipNet, ok := addr.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
			if ipNet.IP.To4() == nil && ipNet.IP.To16() != nil {
				return ipNet.IP.String(), nil
			}
		}
	}

	return "", fmt.Errorf("未找到 IPv6 地址")
}

// DetectIP 检测 IP 地址（根据记录类型返回对应的 IP）
func (s *IPDetectionService) DetectIP(recordType string) (string, error) {
	switch recordType {
	case "A":
		// A 记录优先使用公网 IPv4
		ip, err := s.GetPublicIPv4()
		if err != nil {
			// 降级到本地 IPv4
			return s.GetLocalIPv4()
		}
		return ip, nil
	case "AAAA":
		// AAAA 记录优先使用公网 IPv6
		ip, err := s.GetPublicIPv6()
		if err != nil {
			// 降级到本地 IPv6
			return s.GetLocalIPv6()
		}
		return ip, nil
	default:
		return "", fmt.Errorf("不支持的记录类型：%s", recordType)
	}
}
