package main

// #include <stdlib.h>
import "C"
import (
	"crypto/md5"
	"encoding/json"
	"fmt"
	"github.com/parnurzeal/gorequest"
	"log"
	"math/rand"
	"net/url"
	"strings"
	"sync"
	"time"
)

// 代理类型常量
const (
	CalfElephantProxyType = "CALF_ELEPHANT_PROXY"
	TailProxyType         = "TAIL_PROXY"
)

// 代理服务器列表
var (
	servers = []string{
		"http-dynamic.xiaoxiangdaili.com",
		"http-dynamic-S02.xiaoxiangdaili.com",
		"http-dynamic-S03.xiaoxiangdaili.com",
		"http-dynamic-S04.xiaoxiangdaili.com",
	}
	randMutex  sync.Mutex
	globalRand *rand.Rand

	// 代理健康状态管理
	proxyHealthMaps  = make(map[string]*ProxyHealth)
	proxyHealthMutex sync.RWMutex
)

// ProxyManager 代理管理器结构体
type ProxyManager struct {
	servers        []string `json:"servers"`          // 代理服务器列表
	username       string   `json:"username"`         // 代理账号
	password       string   `json:"password"`         // 代理密码
	tailCardSecret string   `json:"tail_card_secret"` // 尾巴代理卡密
	proxyType      string   `json:"proxy_type"`       // 代理类型 CALF_ELEPHANT_PROXY/TAIL_PROXY
}

// 代理健康状态
type ProxyHealth struct {
	SuccessCount int           // 成功次数
	FailCount    int           // 失败次数
	LastCheck    time.Time     // 最后检查时间
	ResponseTime time.Duration // 响应时间
	IsHealthy    bool          // 是否健康
}

func init() {
	// 创建全局的随机数生成器
	globalRand = rand.New(rand.NewSource(time.Now().UnixNano()))
}

// 获取代理URL
func proxyTypeManager(proxyType, username, password, machineCode string) (string, error) {
	switch proxyType {
	case CalfElephantProxyType:
		return buildCalfElephantProxyURL(username, password)
	case TailProxyType:
		return buildTailProxyURL(machineCode)
	default:
		return "", fmt.Errorf("不支持的代理类型: %s", proxyType)
	}
}

// 构建小象代理URL
func buildCalfElephantProxyURL(username, password string) (string, error) {
	server := randomServer()
	proxyURL := fmt.Sprintf("http://%s:%s@%s:%d",
		url.QueryEscape(username),
		url.QueryEscape(password),
		server,
		10030)

	// 检测代理可用性
	if err := checkProxyHealth(proxyURL); err != nil {
		log.Printf("[WARN] 代理 %s 检测失败: %v", server, err)
		// 尝试下一个代理服务器
		return tryNextCalfElephantProxy(username, password, server)
	}

	log.Printf("[INFO] 使用小象代理: %s", server)
	return proxyURL, nil
}

// 尝试下一个小象代理服务器
func tryNextCalfElephantProxy(username, password, failedServer string) (string, error) {
	// 创建服务器副本并排除失败的服务器
	availableServers := make([]string, 0)
	for _, server := range servers {
		if server != failedServer {
			availableServers = append(availableServers, server)
		}
	}

	if len(availableServers) == 0 {
		return "", fmt.Errorf("所有小象代理服务器都不可用")
	}

	// 随机尝试可用服务器
	for _, server := range shuffleServers(availableServers) {
		proxyURL := fmt.Sprintf("http://%s:%s@%s:%d",
			url.QueryEscape(username),
			url.QueryEscape(password),
			server,
			10030)

		if err := checkProxyHealth(proxyURL); err == nil {
			log.Printf("[INFO] 切换到可用代理: %s", server)
			return proxyURL, nil
		}
		log.Printf("[WARN] 代理 %s 检测失败", server)
	}

	return "", fmt.Errorf("所有可用的小象代理服务器都检测失败")
}

// 构建内置代理URL
func buildTailProxyURL(machineCode string) (string, error) {
	proxies, err := getProxies(machineCode)
	if err != nil {
		return "", err
	}
	if len(proxies) == 0 {
		return "", fmt.Errorf("未获取到有效代理")
	}

	// 过滤并选择健康的代理
	healthyProxies := filterHealthyProxies(proxies)
	if len(healthyProxies) > 0 {
		proxyURL := "http://" + randomElement(healthyProxies)
		log.Printf("[INFO] 使用健康尾巴代理: %s", proxyURL)
		return proxyURL, nil
	}

	// 如果没有健康代理，检测所有代理
	log.Printf("[INFO] 未找到健康代理，开始检测代理可用性...")
	return findWorkingTailProxy(proxies)
}

// 过滤健康代理
func filterHealthyProxies(proxies []string) []string {
	proxyHealthMutex.RLock()
	defer proxyHealthMutex.RUnlock()

	var healthy []string
	for _, proxy := range proxies {
		if health, exists := proxyHealthMaps[proxy]; exists && health.IsHealthy {
			// 检查是否在最近检查过（5分钟内）
			if time.Since(health.LastCheck) < 5*time.Minute {
				healthy = append(healthy, proxy)
			}
		}
	}
	return healthy
}

// 查找可用的尾巴代理
func findWorkingTailProxy(proxies []string) (string, error) {
	// 打乱代理顺序
	shuffledProxies := shuffleServers(proxies)

	// 并发检测代理
	type proxyResult struct {
		proxy string
		err   error
	}

	ch := make(chan proxyResult, len(shuffledProxies))
	var wg sync.WaitGroup

	// 限制并发数
	sem := make(chan struct{}, 5)

	for _, proxy := range shuffledProxies {
		wg.Add(1)
		go func(p string) {
			defer wg.Done()
			sem <- struct{}{}
			defer func() { <-sem }()

			proxyURL := "http://" + p
			err := checkProxyHealth(proxyURL)
			ch <- proxyResult{proxy: p, err: err}
		}(proxy)
	}

	wg.Wait()
	close(ch)

	// 收集结果
	var workingProxies []string
	for result := range ch {
		if result.err == nil {
			workingProxies = append(workingProxies, result.proxy)
			// 更新健康状态
			updateProxyHealth(result.proxy, true, 0)
		} else {
			updateProxyHealth(result.proxy, false, 0)
		}
	}

	if len(workingProxies) > 0 {
		selected := randomElement(workingProxies)
		log.Printf("[INFO] 找到可用代理: %s (共 %d 个可用)", selected, len(workingProxies))
		return "http://" + selected, nil
	}

	return "", fmt.Errorf("所有尾巴代理都不可用")
}

// 检测代理健康状态
func checkProxyHealth(proxyURL string) error {
	start := time.Now()

	req := gorequest.New().Proxy(proxyURL).Timeout(10 * time.Second)
	resp, _, errs := req.Get("https://shop.kongfz.com/").End()

	responseTime := time.Since(start)

	if len(errs) > 0 {
		updateProxyHealth(proxyURL, false, responseTime)
		return fmt.Errorf("代理连接失败: %v", errs)
	}

	if resp.StatusCode != 200 {
		updateProxyHealth(proxyURL, false, responseTime)
		return fmt.Errorf("代理响应状态码错误: %d", resp.StatusCode)
	}

	updateProxyHealth(proxyURL, true, responseTime)
	log.Printf("[DEBUG] 代理 %s 检测成功, 响应时间: %v", getProxyHost(proxyURL), responseTime)
	return nil
}

// 更新代理健康状态
func updateProxyHealth(proxyURL string, success bool, responseTime time.Duration) {
	proxyHealthMutex.Lock()
	defer proxyHealthMutex.Unlock()

	host := getProxyHost(proxyURL)
	if _, exists := proxyHealthMaps[host]; !exists {
		proxyHealthMaps[host] = &ProxyHealth{}
	}

	health := proxyHealthMaps[host]
	health.LastCheck = time.Now()

	if success {
		health.SuccessCount++
		health.FailCount = 0
		health.ResponseTime = responseTime
		health.IsHealthy = true
	} else {
		health.FailCount++
		health.SuccessCount = 0
		// 连续失败3次标记为不健康
		if health.FailCount >= 3 {
			health.IsHealthy = false
		}
	}
}

// 获取代理主机名
func getProxyHost(proxyURL string) string {
	if strings.HasPrefix(proxyURL, "http://") {
		proxyURL = proxyURL[7:]
	}
	// 去除认证信息
	if atIndex := strings.Index(proxyURL, "@"); atIndex != -1 {
		proxyURL = proxyURL[atIndex+1:]
	}
	// 去除端口
	if colonIndex := strings.Index(proxyURL, ":"); colonIndex != -1 {
		proxyURL = proxyURL[:colonIndex]
	}
	return proxyURL
}

// 随机代理服务器
func randomServer() string {
	return randomElement(servers)
}

// 线程安全的随机元素选择
func randomElement(slice []string) string {
	randMutex.Lock()
	defer randMutex.Unlock()
	return slice[globalRand.Intn(len(slice))]
}

// 打乱服务器顺序
func shuffleServers(servers []string) []string {
	randMutex.Lock()
	defer randMutex.Unlock()

	shuffled := make([]string, len(servers))
	copy(shuffled, servers)
	globalRand.Shuffle(len(shuffled), func(i, j int) {
		shuffled[i], shuffled[j] = shuffled[j], shuffled[i]
	})
	return shuffled
}

// 检查卡密是否过期
func checkTailCardSecretExpired(tailCardSecret string) (bool, error) {
	code, err := getMachineCode(tailCardSecret)
	if err != nil {
		return false, fmt.Errorf("请求错误: %v", err)
	}
	targetTime, err := time.Parse("2006-01-02 15:04:05", code.Data.IpExpTime)
	if err != nil {
		return false, fmt.Errorf("时间格式错误: %v", err)
	}
	currentTime := time.Now()
	if targetTime.After(currentTime) {
		return true, nil
	} else {
		return false, fmt.Errorf("卡密已经过期！过期时间: %v", targetTime)
	}
}

// 定义响应结构体
type getMachineCodeResp struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
	Data    struct {
		MachineCode string `json:"machine_code"`
		IpExpTime   string `json:"ip_exp_time"`
		IpThread    int    `json:"ip_thread"`
		IpCardCode  string `json:"ip_card_code"`
	} `json:"data"`
}

// 查询机器码
func getMachineCode(tailCardSecret string) (*getMachineCodeResp, error) {
	url := "http://114.66.2.223:7842/api/proxies/ip_show"
	data := map[string]interface{}{
		"ip_card_code": tailCardSecret,
		"agent_id":     9999,
	}
	_, body, errs := gorequest.New().Post(url).Send(data).End()
	if len(errs) > 0 {
		return nil, fmt.Errorf("查询机器码失败: %v", errs)
	}
	var resp getMachineCodeResp
	if err := json.Unmarshal([]byte(body), &resp); err != nil {
		return nil, fmt.Errorf("解析响应失败: %v", err)
	}

	if resp.Code == 201 {
		machineCode, err := rechargeCard(tailCardSecret, resp.Data.MachineCode)
		if err != nil {
			return nil, err
		}
		resp.Data.MachineCode = machineCode
		return &resp, nil
	} else if resp.Code == 200 {
		return &resp, nil
	} else {
		return nil, fmt.Errorf("查询机器码失败: %s", resp.Message)
	}
}

// 充值卡密
func rechargeCard(tailCardSecret, machineCode string) (string, error) {
	url := "http://114.66.2.223:7842/api/proxies/ip_recharge"
	data := map[string]interface{}{
		"machine_code": machineCode,
		"ip_card_code": tailCardSecret,
		"agent_id":     9999,
	}
	_, body, errs := gorequest.New().Post(url).Send(data).End()
	if len(errs) > 0 {
		return "", fmt.Errorf("充值卡密失败: %v", errs)
	}
	var resp struct {
		Code    int    `json:"code"`    // 状态码
		Message string `json:"message"` // 返回消息
		Data    struct {
			IpExpTime   string `json:"ip_exp_time"`  // 过期时间
			IpThread    int    `json:"ip_thread"`    // 线程
			MachineCode string `json:"machine_code"` // 机器码
		} `json:"data"`
	}
	if err := json.Unmarshal([]byte(body), &resp); err != nil {
		return "", fmt.Errorf("解析响应失败: %v", err)
	}
	if resp.Code != 200 {
		return "", fmt.Errorf("充值卡密失败: %s", resp.Message)
	}
	return resp.Data.MachineCode, nil
}

// 获取代理服务器列表
func getProxies(machineCode string) ([]string, error) {
	log.Printf("[INFO] 开始获取代理列表: %s", machineCode)
	// 生成签名
	sign := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("9999%s9999", machineCode))))

	GetProxiesUrl := fmt.Sprintf("http://114.66.2.223:7842/api/proxies/get_proxy?machine_code=%s&sign=%s&agent_id=9999",
		machineCode, sign)

	req := gorequest.New().Get(GetProxiesUrl).Timeout(20 * time.Second)
	_, body, errs := req.End()
	if len(errs) > 0 {
		return nil, fmt.Errorf("获取代理失败: %v", errs)
	}

	// 检查是否为JSON错误响应
	if strings.HasPrefix(strings.TrimSpace(body), "{") && strings.HasSuffix(strings.TrimSpace(body), "}") {
		// 尝试解析为JSON错误响应
		var errorResp struct {
			Code    int    `json:"code"`
			Message string `json:"message"`
		}
		if err := json.Unmarshal([]byte(body), &errorResp); err == nil {
			return nil, fmt.Errorf("获取代理失败: %s (错误码: %d)", errorResp.Message, errorResp.Code)
		}
	}

	// 解析响应
	lines := strings.Split(strings.TrimSpace(body), "\n")
	var proxies []string
	for _, line := range lines {
		line = strings.TrimSpace(line)
		if line != "" && !strings.HasPrefix(line, "{") {
			proxies = append(proxies, line)
		}
	}
	if len(proxies) == 0 {
		return nil, fmt.Errorf("未获取到有效代理")
	}

	log.Printf("[INFO] 获取到 %d 个代理", len(proxies))
	return proxies, nil
}

// 初始化代理信息
func initProxy() {

}

// 导出函数：获取代理健康状态（用于调试）
//
//export GetProxyHealth
func GetProxyHealth() *C.char {
	proxyHealthMutex.RLock()
	defer proxyHealthMutex.RUnlock()

	healthInfo := make(map[string]interface{})
	for proxy, health := range proxyHealthMaps {
		healthInfo[proxy] = map[string]interface{}{
			"success_count": health.SuccessCount,
			"fail_count":    health.FailCount,
			"last_check":    health.LastCheck.Format(time.RFC3339),
			"response_time": health.ResponseTime.String(),
			"is_healthy":    health.IsHealthy,
		}
	}

	jsonData, err := json.Marshal(healthInfo)
	if err != nil {
		return C.CString(fmt.Sprintf(`{"error": "序列化健康信息失败: %v"}`, err))
	}

	return C.CString(string(jsonData))
}

// 导出函数：代理类型管理器
//
//export ProxyTypeManager
func ProxyTypeManager(proxyType, username, password, machineCode *C.char) *C.char {
	goProxyType := C.GoString(proxyType)
	goUsername := C.GoString(username)
	goPassword := C.GoString(password)
	goMachineCode := C.GoString(machineCode)

	log.Printf("[DEBUG] 代理类型管理器调用: type=%s", goProxyType)

	proxyURL, err := proxyTypeManager(goProxyType, goUsername, goPassword, goMachineCode)
	if err != nil {
		errorMsg := fmt.Sprintf("ERROR: %v", err)
		log.Printf("[ERROR] 代理类型管理器错误: %v", err)
		return C.CString(errorMsg)
	}

	log.Printf("[DEBUG] 代理类型管理器返回: %s", proxyURL)
	return C.CString(proxyURL)
}

//// 导出函数：释放C字符串内存
////
////export FreeCString
//func FreeCString(str *C.char) {
//	C.free(unsafe.Pointer(str))
//}
//
//func main() {
//
//}
