package main

/*
   #include <stdlib.h>

   // proxyConfig.dll 函数声明
   extern char* ProxyTypeManager(char* proxyType, char* username, char* password, char* machineCode);
   extern void FreeCString(char* str);
*/
import "C"
import (
	"context"
	"database/sql"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"math/rand"
	"net/http"
	"os"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"syscall"
	"time"
	"unsafe"

	"github.com/PuerkitoBio/goquery"
	"github.com/chromedp/chromedp"
	_ "github.com/go-sql-driver/mysql"
	"github.com/parnurzeal/gorequest"
)

const (
	UseProxy = "proxy"  // 使用代理
	NotProxy = "direct" // 不用代理代理
)

type Config struct {
	App struct {
		MaxRetryTimes    int           `ini:"app.max_retry_times" json:"max_retry_times" default:"3"`
		RateLimitDelay   time.Duration `ini:"app.rate_limit_delay" json:"rate_limit_delay" default:"500ms"`
		Size             int           `ini:"app.size" json:"size" default:"5"`
		DefaultUserAgent string        `ini:"app.default_user_agent" json:"default_user_agent" default:"Mozilla/5.0"`
	} `ini:"app" json:"app"`

	API struct {
		LoginURL         string `ini:"api.login_url" json:"login_url" default:"https://login.kongfz.com/Pc/Login/account"`
		BookSearchURL    string `ini:"api.book_search_url" json:"book_search_url" default:"https://search.kongfz.com/pc-gw/search-web/client/pc/bookLib/keyword/list"`
		ProductSearchURL string `ini:"api.product_search_url" json:"product_search_url" default:"https://search.kongfz.com/pc-gw/search-web/client/pc/product/keyword/list"`
	} `ini:"api" json:"api"`

	Proxy struct {
		Servers         string `ini:"proxy.servers" json:"servers" default:"http-dynamic.xiaoxiangdaili.com,http-dynamic-S02.xiaoxiangdaili.com,http-dynamic-S03.xiaoxiangdaili.com,http-dynamic-S04.xiaoxiangdaili.com"`
		Username        string `ini:"proxy.username" json:"username" default:"1297757178467602432"`
		Password        string `ini:"proxy.password" json:"password" default:"QgQBvP7f"`
		TailMachineCode string `ini:"proxy.tail_machine_code" json:"tail_machine_code" default:"b7bf22a237ec692f13fcc2c43ee63252"`
		TailCardKey     string `ini:"proxy.tail_card_key" json:"tail_card_key" default:"DL_20_YK_1920acb2129844c2aabade3896560a9b"`
		ProxyFilePath   string `ini:"proxy.proxy_file_path" json:"proxy_file_path" default:"dll/proxyConfig.dll"`
	} `ini:"proxy" json:"proxy"`

	Database struct {
		Username string `ini:"database.username" json:"username" default:"newAdmin"`
		Password string `ini:"database.password" json:"password" default:"bYPp8SbBe5F7nz2i"`
		Host     string `ini:"database.host" json:"host" default:"146.56.227.42:3306"`
		Name     string `ini:"database.name" json:"name" default:"newadmin"`
	} `ini:"database" json:"database"`
}

// 条目详情结构体
type BookInfo struct {
	BookName           string `json:"book_name"`            // 书名
	Author             string `json:"author"`               // 作者
	Publisher          string `json:"publisher"`            // 出版社
	ISBN               string `json:"isbn"`                 // ISBN
	PublicationTime    int64  `json:"publication_time"`     // 出版时间
	Edition            string `json:"edition"`              // 版次
	PrintTime          string `json:"print_time"`           // 印刷时间
	FixPrice           string `json:"fix_price"`            // 定价
	BindingLayout      string `json:"binding_layout"`       // 装帧
	Format             string `json:"format"`               // 开本
	Paper              string `json:"paper"`                // 纸张
	Pages              string `json:"pages"`                // 页数
	Wordage            string `json:"wordage"`              // 字数
	Languages          string `json:"languages"`            // 语种
	Era                string `json:"era"`                  // 年代
	EngravingMethod    string `json:"engraving_method"`     // 刻印方式
	Dimensions         string `json:"dimensions"`           // 尺寸
	VolumeNumber       string `json:"volume_number"`        // 册数
	BookPic            string `json:"book_pic"`             // 图书封面图(官图)
	BookPicS           string `json:"book_pic_s"`           // 图书封面图(实拍图)
	SellingPrice       string `json:"selling_price"`        // 售价
	Condition          string `json:"condition"`            // 品相
	ExpressDeliveryFee string `json:"express_delivery_fee"` // 快递费
	Editor             string `json:"editor"`               // 编辑
	Category           string `json:"category"`             // 分类
	BuyCount           string `json:"buy_count"`            // 买过
	SellCount          string `json:"sell_count"`           // 在卖
	Content            string `json:"content"`              // 内容
	Mid                int64  `json:"mid"`                  // 商家id
	ItemId             int64  `json:"item_id"`              // 商品id
	ShopId             int64  `json:"shop_id"`              // 店铺id
	DetailUrl          string `json:"detail_url"`           // 商品详情url
}

// API响应结构
type APIResp struct {
	Success  bool        `json:"success"`
	Message  string      `json:"message,omitempty"`
	GoodsNum string      `json:"goods_num,omitempty"`
	PNum     string      `json:"pnum,omitempty"`
	Data     interface{} `json:"data,omitempty"`
	Error    string      `json:"error,omitempty"`
}

// APIResponse
type APIResponse struct {
	Success bool        `json:"success"`
	Message string      `json:"message,omitempty"`
	Data    interface{} `json:"data,omitempty"`
}

// 账号凭证结构
type AccountCredential struct {
	ID       int64
	Username string
	Password string
	Token    string
}

// 全局变量
var (
	cf             Config     // 配置信息
	tailProxyMu    sync.Mutex // 互斥锁
	proxyFailCount int
	mu             sync.RWMutex // 数据库锁

	// 全局代理管理器
	globalProxyManager  *ProxyConfigManager
	proxyManagerOnce    sync.Once
	proxyManagerInitErr error
)

// ProductInfo 商品信息结构
type ProductInfo struct {
	ItemID      string `json:"itemId"`
	BookName    string `json:"bookName"`
	Price       string `json:"price"`
	ShippingFee string `json:"shippingFee"`
}

// ProductResponse 响应结构
type ProductResponse struct {
	Success bool          `json:"success"`
	Message string        `json:"message,omitempty"`
	Data    []ProductInfo `json:"data,omitempty"`
}

// 并行获取详情的结果结构
type DetailResult struct {
	URL   string
	Doc   *goquery.Document
	Error error
	Index int
}

// 第一阶段：收集基本信息并识别需要详情的项目
type BookItem struct {
	Book      BookInfo
	Selection *goquery.Selection
	HasDetail bool
	DetailURL string
	Index     int
}

// 分类项结构体
type SalesCategory struct {
	Key   string `json:"key"`
	Value int    `json:"value"`
}

// 图书详情响应结构体
type BookDetailResponse struct {
	Status     bool     `json:"status"`
	Result     BookList `json:"result"`
	ErrMessage string   `json:"errMessage"`
	ErrCode    int      `json:"errCode"`
}

// 图书列表结构体
type BookList struct {
	Current int               `json:"current"`
	Data    []BookInformation `json:"data"`
	Total   int               `json:"total"`
}

// 图书信息结构体
type BookInformation struct {
	Author              string       `json:"author"`
	BookName            string       `json:"bookName"`
	ContentIntroduction string       `json:"contentIntroduction"`
	ImgUrl              string       `json:"imgUrl"`
	Isbn                string       `json:"isbn"`
	ItemUrls            ItemUrls     `json:"itemUrls"`
	Mid                 int          `json:"mid"`
	NewMinPrice         string       `json:"newMinPrice"`
	OldMinPrice         string       `json:"oldMinPrice"`
	Press               string       `json:"press"`
	Price               string       `json:"price"`
	PubDate             string       `json:"pubDate"`
	RiseTag             string       `json:"riseTag"`
	AuthorArr           []AuthorInfo `json:"authorArr"`
	PressUrl            string       `json:"pressUrl"`
}

// 作者信息结构体
type AuthorInfo struct {
	Name        string `json:"name"`
	OriName     string `json:"oriName"`
	Nationality string `json:"nationality"`
	Role        string `json:"role"`
	Url         string `json:"url"`
}

// 商品链接结构体
type ItemUrls struct {
	AppUrl  string `json:"appUrl"`
	MUrl    string `json:"mUrl"`
	MiniUrl string `json:"miniUrl"`
	PcUrl   string `json:"pcUrl"`
}

type UserInfo struct {
	UserID   int64  `json:"userId"`
	Nickname string `json:"nickname"`
	Mobile   string `json:"mobile"`
}

// ProxyConfigManager 代理配置DLL管理器
type ProxyConfigManager struct {
	dll *syscall.DLL
}

func NewProxyConfigManager(dllPath string) (*ProxyConfigManager, error) {
	dll, err := syscall.LoadDLL(dllPath)
	if err != nil {
		return nil, fmt.Errorf("加载代理配置DLL失败: %v", err)
	}
	return &ProxyConfigManager{dll: dll}, nil
}

func (m *ProxyConfigManager) Close() {
	if m.dll != nil {
		m.dll.Release()
	}
}

// ProxyTypeManager 调用代理类型管理器
func (m *ProxyConfigManager) ProxyTypeManager(proxyType, username, password, machineCode string) (string, error) {
	proc, err := m.dll.FindProc("ProxyTypeManager")
	if err != nil {
		return "", fmt.Errorf("找不到函数 ProxyTypeManager: %v", err)
	}
	// 准备参数
	proxyTypePtr, _ := syscall.BytePtrFromString(proxyType)
	usernamePtr, _ := syscall.BytePtrFromString(username)
	passwordPtr, _ := syscall.BytePtrFromString(password)
	machineCodePtr, _ := syscall.BytePtrFromString(machineCode)
	// 调用函数
	r1, _, err := proc.Call(
		uintptr(unsafe.Pointer(proxyTypePtr)),
		uintptr(unsafe.Pointer(usernamePtr)),
		uintptr(unsafe.Pointer(passwordPtr)),
		uintptr(unsafe.Pointer(machineCodePtr)),
	)

	if err != nil && err.Error() != "The operation completed successfully." {
		return "", fmt.Errorf("调用 ProxyTypeManager 失败: %v", err)
	}
	// 转换结果
	result := (*byte)(unsafe.Pointer(r1))
	var resultBytes []byte
	for i := 0; ; i++ {
		bytePtr := (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(result)) + uintptr(i)))
		if *bytePtr == 0 {
			break
		}
		resultBytes = append(resultBytes, *bytePtr)
	}
	// 释放内存
	freeProc, _ := m.dll.FindProc("FreeCString")
	if freeProc != nil {
		freeProc.Call(r1)
	}
	return string(resultBytes), nil
}

// 登录
func outLogin(username, password string) (string, error) {
	if username == "" || password == "" {
		return "", fmt.Errorf("请输入用户名和密码!")
	}
	formData := map[string]string{
		"loginName": username,
		"loginPass": password,
		"returnUrl": "http://user.kongfz.com/",
	}
	resp, body, errs := gorequest.New().
		Post(cf.API.LoginURL).
		Set("Content-Type", "application/x-www-form-urlencoded").
		Set("User-Agent", cf.App.DefaultUserAgent).
		Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8").
		Send(formData).
		Timeout(15 * time.Second).End()
	if len(errs) > 0 {
		return "", fmt.Errorf("登录请求失败: %v", errs)
	}
	// 检查HTTP状态码
	if resp.StatusCode != http.StatusOK {
		return "", fmt.Errorf("登录失败(HTTP状态码: %d)", resp.StatusCode)
	}
	// 提取Cookie
	cookie := resp.Header.Get("Set-Cookie")
	if strings.Contains(body, "window.location.href='https://login.kongfz.cn/Pc/Session/rsync") {
		if cookie == "" {
			return "", fmt.Errorf("登录成功但未获取到Cookie")
		}
		// 登录成功
		if strings.Contains(cookie, "PHPSESSID=") {
			token := strings.Split(strings.Split(cookie, "PHPSESSID=")[1], ";")[0]
			return token, nil
		}
		return "", fmt.Errorf("登录失败: 未找到PHPSESSID")
	}
	// 错误信息
	var res struct {
		Status  bool   `json:"status"`
		ErrCode int    `json:"errCode"`
		ErrInfo string `json:"errInfo"`
	}
	if err := json.Unmarshal([]byte(body), &res); err == nil {
		if res.ErrCode == 1001 || res.ErrCode == 1005 {
			return "", fmt.Errorf("账号或密码错误！")
		}
		if res.ErrInfo != "" {
			return "", fmt.Errorf("登录失败: %s", res.ErrInfo)
		}
	}
	return "", fmt.Errorf("登录失败，未知错误！")
}

// 获取用户信息(带有Out的都非官方标准接口)
func outGetUserMsg(token string) (*UserInfo, error) {
	url := "https://user.kongfz.com/User/Index/getUserInfo/"
	resp, body, errs := gorequest.New().
		Get(url).
		Set("Cookie", fmt.Sprintf("PHPSESSID=%s", token)).
		Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
		Set("Accept", "application/json, text/plain, */*").
		Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
		Timeout(15 * time.Second).
		End()
	if len(errs) > 0 {
		return nil, fmt.Errorf("查询请求失败: %v", errs)
	}
	//检查HTTP状态码
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("HTTP错误: %s", resp.Status)
	}
	var userInfo struct {
		Status bool `json:"status"`
		Data   struct {
			UserID   int64  `json:"userId"`
			Nickname string `json:"nickname"`
			Mobile   string `json:"mobile"`
		}
	}
	if err := json.Unmarshal([]byte(body), &userInfo); err != nil {
		return nil, fmt.Errorf("解析JSON失败: %w", err)
	}
	user := &UserInfo{}
	if !userInfo.Status {
		return nil, fmt.Errorf("获取用户失败！")
	}
	user.UserID = userInfo.Data.UserID
	user.Nickname = userInfo.Data.Nickname
	user.Mobile = userInfo.Data.Mobile
	return user, nil
}

// 获取商品模版
func outGetGoodsTplMsg(token, itemId, proxy string) (map[string]interface{}, error) {
	if token == "" {
		return nil, fmt.Errorf("请先登录获取Token")
	}
	url := fmt.Sprintf("https://seller.kongfz.com/pc/itemInfo/getTplFields?itemId=%s&isClone=1&v=%d",
		itemId, time.Now().Unix())
	// 创建HTTP客户端
	request := gorequest.New()
	// 设置代理（如果有提供代理URL）
	if proxy != "" {
		request.Proxy(proxy)
	}
	resp, body, errs := request.Get(url).
		Set("Cookie", fmt.Sprintf("PHPSESSID=%s", token)).
		Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
		Set("Accept", "application/json, text/plain, */*").
		Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
		Set("Referer", "https://seller.kongfz.com/").
		Set("Origin", "https://seller.kongfz.com").
		Timeout(15 * time.Second).
		End()
	if errs != nil {
		// 检查是否是代理相关错误
		var isProxyError bool
		var errorDetails []string
		for _, e := range errs {
			errorStr := e.Error()
			errorDetails = append(errorDetails, errorStr)
			if strings.Contains(errorStr, "Proxy Authentication Required") ||
				strings.Contains(errorStr, "connectex: A connection attempt failed") ||
				strings.Contains(errorStr, "connectex: No connection could be made") ||
				strings.Contains(errorStr, "proxyconnect tcp") ||
				strings.Contains(errorStr, "timeout") ||
				strings.Contains(errorStr, "connection refused") {
				isProxyError = true
			}
		}
		log.Printf("[ERROR] 请求错误详情: %v", errorDetails)
		if isProxyError {
			// 处理代理失败
			return nil, fmt.Errorf("代理连接失败")
		}
		return nil, fmt.Errorf("查询请求失败: %v", errs)
	}
	//检查HTTP状态码
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("HTTP错误: %s", resp.Status)
	}
	var data map[string]interface{}
	if err := json.Unmarshal([]byte(body), &data); err != nil {
		return nil, fmt.Errorf("解析JSON失败: %w", err)
	}
	if val, ok := data["status"].(float64); ok && val == 1 {
		return data, nil
	}
	return nil, fmt.Errorf("API返回错误: %+v", data)
}

// 获取商品列表
func outGetGoodsListMsgFromSelfShop(token string, proxy string, itemSn string, priceMin string, priceMax string, startCreateTime int,
	endCreateTime int, requestType string, isItemSnEqual int, page int, size int) (map[string]interface{}, error) {
	if token == "" {
		return nil, fmt.Errorf("请先登录获取Token")
	}
	url := "https://seller.kongfz.com/pc-gw/book-manage-service/client/pc/goods/unSold/list"
	formData := struct {
		ItemSn          string `json:"itemSn"`
		PriceMin        string `json:"priceMin"`
		PriceMax        string `json:"priceMax"`
		StartCreateTime int    `json:"startCreateTime"`
		EndCreateTime   int    `json:"endCreateTime"`
		RequestType     string `json:"requestType,omitempty"`
		IsItemSnEqual   int    `json:"isItemSnEqual,omitempty"`
		Page            int    `json:"page,omitempty"`
		Size            int    `json:"size,omitempty"`
	}{
		ItemSn:          itemSn,
		PriceMin:        priceMin,
		PriceMax:        priceMax,
		StartCreateTime: startCreateTime,
		EndCreateTime:   endCreateTime,
		RequestType:     requestType,
		IsItemSnEqual:   isItemSnEqual,
		Page:            page,
		Size:            size,
	}
	request := gorequest.New()
	if proxy != "" {
		request.Proxy(proxy)
	}
	resp, body, errs := request.Post(url).
		Set("Cookie", fmt.Sprintf("PHPSESSID=%s", token)).
		Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
		Set("Accept", "application/json, text/plain, */*").
		Send(formData).
		Timeout(15 * time.Second).
		End()
	if errs != nil {
		// 检查是否是代理相关错误
		var isProxyError bool
		var errorDetails []string
		for _, e := range errs {
			errorStr := e.Error()
			errorDetails = append(errorDetails, errorStr)
			if strings.Contains(errorStr, "Proxy Authentication Required") ||
				strings.Contains(errorStr, "connectex: A connection attempt failed") ||
				strings.Contains(errorStr, "connectex: No connection could be made") ||
				strings.Contains(errorStr, "proxyconnect tcp") ||
				strings.Contains(errorStr, "timeout") ||
				strings.Contains(errorStr, "connection refused") {
				isProxyError = true
			}
		}
		log.Printf("[ERROR] 请求错误详情: %v", errorDetails)
		if isProxyError {
			// 处理代理失败
			return nil, fmt.Errorf("代理连接失败")
		}
		return nil, fmt.Errorf("查询请求失败: %v", errs)
	}
	//检查HTTP状态码
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("HTTP错误: %s", resp.Status)
	}
	var data map[string]interface{}
	if err := json.Unmarshal([]byte(body), &data); err != nil {
		return nil, fmt.Errorf("解析JSON失败: %w", err)
	}
	if val, ok := data["status"]; ok && val == 1 {
		return data, nil
	}
	return nil, fmt.Errorf("API返回错误: %+v", data)
}

// 新增商品(带有Out的都非官方标准接口)
func outAddGoods(token, proxy, formData string) (map[string]interface{}, error) {
	url := "https://seller.kongfz.com/pc/itemInfo/add"
	request := gorequest.New()
	if proxy != "" {
		request.Proxy(proxy)
	}
	resp, body, errs := request.Post(url).
		Set("Cookie", fmt.Sprintf("PHPSESSID=%s", token)).
		Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
		Set("Accept", "application/json, text/plain, */*").
		Send(formData).
		Timeout(15 * time.Second).
		End()
	if errs != nil {
		// 检查是否是代理相关错误
		var isProxyError bool
		var errorDetails []string
		for _, e := range errs {
			errorStr := e.Error()
			errorDetails = append(errorDetails, errorStr)
			if strings.Contains(errorStr, "Proxy Authentication Required") ||
				strings.Contains(errorStr, "connectex: A connection attempt failed") ||
				strings.Contains(errorStr, "connectex: No connection could be made") ||
				strings.Contains(errorStr, "proxyconnect tcp") ||
				strings.Contains(errorStr, "timeout") ||
				strings.Contains(errorStr, "connection refused") {
				isProxyError = true
			}
		}
		log.Printf("[ERROR] 请求错误详情: %v", errorDetails)
		if isProxyError {
			// 处理代理失败
			return nil, fmt.Errorf("代理连接失败")
		}
		return nil, fmt.Errorf("查询请求失败: %v", errs)
	}
	//检查HTTP状态码
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("HTTP错误: %s", resp.Status)
	}
	var data map[string]interface{}
	if err := json.Unmarshal([]byte(body), &data); err != nil {
		return nil, fmt.Errorf("解析JSON失败: %w", err)
	}
	if val, ok := data["status"]; ok && val == 1 {
		return data, nil
	}
	return nil, fmt.Errorf("API返回错误: %+v", data)
}

// 获取图片URL(官图和拍图)
func outGetImageByIsbn(token string, isbn string, proxy string, isLiveImage int, isReturnMsg int) (*BookInfo, error) {
	fmt.Println("[DEBUG] 使用的ISBN: ", isbn)
	// isLiveImage 1实拍图 0官图 ，isReturnMsg 0商品信息
	bookInfo := &BookInfo{}
	if isLiveImage == 0 {
		// 孔网官图请求
		gtUrl := fmt.Sprintf("%s?keyword=%s", cf.API.BookSearchURL, isbn)
		// 创建HTTP客户端
		requestGt := gorequest.New()
		// 设置代理(如果有提供代理URL)
		if proxy != "" {
			requestGt.Proxy(proxy)
		}
		// 发送请求
		respGt, bodyGt, errsGt := requestGt.Get(gtUrl).
			Set("Cookie", token).
			Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
			Set("Accept", "application/json, text/plain, */*").
			Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
			Set("Referer", "https://item.kongfz.com/").
			Timeout(30 * time.Second).
			End()
		if len(errsGt) > 0 {
			// 检查是否是代理相关错误
			var isProxyError bool
			var errorDetails []string
			for _, e := range errsGt {
				errorStr := e.Error()
				errorDetails = append(errorDetails, errorStr)
				if strings.Contains(errorStr, "Proxy Authentication Required") ||
					strings.Contains(errorStr, "connectex: A connection attempt failed") ||
					strings.Contains(errorStr, "connectex: No connection could be made") ||
					strings.Contains(errorStr, "proxyconnect tcp") ||
					strings.Contains(errorStr, "timeout") ||
					strings.Contains(errorStr, "connection refused") {
					isProxyError = true
				}
			}
			log.Printf("[ERROR] 请求错误详情: %v", errorDetails)
			if isProxyError {
				// 处理代理失败
				return nil, fmt.Errorf("代理连接失败")
			}
			return nil, fmt.Errorf("查询请求失败: %v", errsGt)
		}
		//检查HTTP状态码
		if respGt.StatusCode != http.StatusOK {
			return nil, fmt.Errorf("HTTP错误: %s", respGt.Status)
		}
		// 解析响应
		var apiGtResp struct {
			Status     int    `json:"status"`
			ErrType    string `json:"errType"`
			Message    string `json:"message"`
			SystemTime int64  `json:"systemTime"`
			Data       struct {
				ItemResponse struct {
					Total int `json:"total"`
					List  []struct {
						BookName     string `json:"bookName"`
						Mid          int64  `json:"mid"`
						ImgUrlEntity struct {
							BigImgUrl string `json:"bigImgUrl"`
						} `json:"imgUrlEntity"`
						Isbn         string   `json:"isbn"`
						BookShowInfo []string `json:"bookShowInfo"`
					} `json:"list"`
				} `json:"itemResponse"`
			} `json:"data"`
		}
		if err := json.Unmarshal([]byte(bodyGt), &apiGtResp); err != nil {
			return nil, fmt.Errorf("解析JSON失败: %w", err)
		}
		if apiGtResp.ErrType == "102" {
			return nil, fmt.Errorf("错误信息: %w，状态码: %s", apiGtResp.Message, apiGtResp.ErrType)
		}
		// 如果找到条目，返回图片URL
		if apiGtResp.Data.ItemResponse.Total > 0 && len(apiGtResp.Data.ItemResponse.List) > 0 {
			list := apiGtResp.Data.ItemResponse.List[0]
			bookShowInfo := list.BookShowInfo
			bookInfo.BookName = list.BookName
			bookInfo.BookPic = list.ImgUrlEntity.BigImgUrl
			bookInfo.ISBN = list.Isbn
			// 根据长度安全填充字段
			if isReturnMsg == 0 {
				if len(bookShowInfo) > 0 {
					bookInfo.Author = bookShowInfo[0]
				}
				if len(bookShowInfo) > 1 {
					bookInfo.Publisher = bookShowInfo[1]
				}
				if len(bookShowInfo) > 2 {
					bookInfo.PublicationTime = validateDateFormat(bookShowInfo[2])
				}
				if len(bookShowInfo) > 3 {
					bookInfo.BindingLayout = bookShowInfo[3]
				}
				if len(bookShowInfo) > 4 {
					bookInfo.FixPrice = bookShowInfo[4]
				} else {
					log.Printf("[WARN] BookShowInfo 长度不足 (仅 %d 项): %v", len(bookShowInfo), bookShowInfo)
				}
			}
		}
		return bookInfo, nil
	}
	if isLiveImage == 1 {
		// 实拍图
		sptUrl := fmt.Sprintf("%s?dataType=0&keyword=%s&page=1&size=%d&sortType=7&actionPath=quality,sortType&quality=85~&quaSelect=2&userArea=13003000000", cf.API.ProductSearchURL, isbn, cf.App.Size)
		//创建HTTP客户端
		requestSpt := gorequest.New()
		//设置代理(如果有提供代理URL)
		if proxy != "" {
			requestSpt.Proxy(proxy)
		}
		// 发送请求
		respSpt, bodySpt, errsSpt := requestSpt.Get(sptUrl).
			Proxy(proxy).
			Set("Cookie", token).
			Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
			Set("Accept", "application/json, text/plain, */*").
			Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
			Set("Referer", "https://item.kongfz.com/").
			Timeout(30 * time.Second).
			End()
		// 错误处理
		if len(errsSpt) > 0 {
			return nil, fmt.Errorf("请求失败: %v", errsSpt)
		}
		// 检查HTTP状态码
		if respSpt.StatusCode != http.StatusOK {
			return nil, fmt.Errorf("HTTP错误: %s", respSpt.Status)
		}
		// 解析响应
		var apiSptResp struct {
			Status     int    `json:"status"`
			ErrType    string `json:"errType"`
			Message    string `json:"message"`
			SystemTime int64  `json:"systemTime"`
			Data       struct {
				ItemResponse struct {
					Total int `json:"total"`
					List  []struct {
						ItemId      int64  `json:"itemId"`
						Title       string `json:"title"`
						ImgUrl      string `json:"imgUrl"`
						ImgBigUrl   string `json:"imgBigUrl"`
						Author      string `json:"author"`
						PubDateText string `json:"pubDateText"`
						Isbn        string `json:"isbn"`
						Press       string `json:"press"`
						ShopId      int64  `json:"shopId"`
						TplRecords  []struct {
							Key   string `json:"key"`
							Value string `json:"value"`
						} `json:"tplRecords"`
					} `json:"list"`
				} `json:"itemResponse"`
			} `json:"data"`
		}
		// 解析JSON
		if err := json.Unmarshal([]byte(bodySpt), &apiSptResp); err != nil {
			return nil, fmt.Errorf("解析JSON失败: %w", err)
		}
		if apiSptResp.ErrType == "102" {
			return nil, fmt.Errorf("错误信息: %w，状态码: %s", apiSptResp.Message, apiSptResp.ErrType)
		}
		if apiSptResp.Data.ItemResponse.Total > 0 && len(apiSptResp.Data.ItemResponse.List) > 0 {
			// 确定其实索引
			var startIndex int
			if cf.App.Size >= apiSptResp.Data.ItemResponse.Total {
				startIndex = apiSptResp.Data.ItemResponse.Total - 1
			} else {
				startIndex = cf.App.Size - 1
			}
			for attempt := 0; attempt < 3; attempt++ {
				currentIndex := startIndex - attempt
				// 检查索引是否有效
				if currentIndex < 0 || currentIndex >= len(apiSptResp.Data.ItemResponse.List) {
					log.Printf("[DEBUG] 索引 %d 超出范围，跳过", currentIndex)
					continue
				}
				randomNum := rand.Intn(currentIndex + 1)
				item := apiSptResp.Data.ItemResponse.List[randomNum]
				// 检查图片URL是否存在
				if item.ImgBigUrl == "" {
					log.Printf("[DEBUG] 索引 %d 的图片URL为空，跳过", randomNum)
					continue
				}
				// 响应信息
				bookInfo.BookPicS = item.ImgUrl
				bookInfo.ISBN = item.Isbn
				if bookInfo.BookName == "" {
					bookInfo.BookName = item.Title
					if isReturnMsg == 0 {
						// 安全地获取TplRecords中的值
						if len(item.TplRecords) > 0 {
							bookInfo.Author = item.TplRecords[0].Value
						}
						if len(item.TplRecords) > 1 {
							bookInfo.Publisher = item.TplRecords[1].Value
						}
						if len(item.TplRecords) > 2 {
							bookInfo.PublicationTime = validateDateFormat(item.TplRecords[2].Value)
						}
						if len(item.TplRecords) > 3 {
							bookInfo.BindingLayout = item.TplRecords[3].Value
						}
					}
				}
				return bookInfo, nil
			}
		}
	}
	return nil, fmt.Errorf("查询失败，没有数据！")
}

// 登录，获取账号cookie
func loginCookie() (cookie string, err error) {
	account := &AccountCredential{
		ID:       0,
		Username: "",
		Password: "",
		Token:    "",
	}
	var change = false
	if account.Username == "" || change {
		account, err = getRandomAccount()
		if err != nil {
			log.Printf("获取账号失败: %v", err)
		}
		change = false
	}
	fmt.Println("获取的账号: ", account.Username)
	// 将拿出的账号token赋值给cookie
	cookie = account.Token
	// 若cookie为""说明该账号没有token还未登录过，进行登录
	if cookie == "" {
		// 登录获取cookie
		cookie, err = loginAndGetCookie(account)
		if err != nil {
			// 若登录失败，则标记为需要更换账号，然后重试
			change = true
			log.Printf("登录获取cookie失败: %v ，更换账号重试", err)
		}
		// 成功拿到cookie,则将新拿到的cookie赋值给account的token
		account.Token = cookie
		// 将新拿到的cookie同步更新token到数据库
		err = updateAccountToken(account.ID, cookie)
		if err != nil {
			log.Printf("更新账号token失败: %v", err)
		}
	}
	return cookie, nil
}

// 登录并获取cookie
func loginAndGetCookie(account *AccountCredential) (string, error) {
	formData := map[string]string{
		"loginName": account.Username,
		"loginPass": account.Password,
	}
	// 没有代理
	resp, body, errs := gorequest.New().
		Post(cf.API.LoginURL).
		Set("Content-Type", "application/x-www-form-urlencoded").
		Set("User-Agent", cf.App.DefaultUserAgent).
		Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8").
		Send(formData).
		Timeout(30 * time.Second).
		End()
	// 处理请求错误
	if len(errs) > 0 {
		// 检查是否是代理认证失败
		var proxyAuthFailed bool
		for _, e := range errs {
			if strings.Contains(e.Error(), "Proxy Authentication Required") {
				proxyAuthFailed = true
				break
			}
		}
		if proxyAuthFailed {
			return "", fmt.Errorf("代理认证失败")
		}
		return "", fmt.Errorf("登录请求失败: %v", errs)
	}
	// 检查HTTP状态码
	if resp.StatusCode != http.StatusOK {
		return "", fmt.Errorf("登录失败(HTTP状态码: %d)", resp.StatusCode)
	}
	if !strings.Contains(body, "window.location.href='https://login.kongfz.cn/Pc/Session/rsync") {
		// 尝试解析JSON响应获取错误信息
		var response struct {
			Status  bool   `json:"status"`
			ErrCode *int   `json:"errCode"`
			ErrInfo string `json:"errInfo"`
		}
		if err := json.Unmarshal([]byte(body), &response); err != nil {
			// 账号密码错误
			if response.ErrCode != nil && *response.ErrCode == 1001 {
				// 标记账号为不可用
				if err := updateAccountInvalid(account.ID); err != nil {
					log.Printf("标记账号不可用失败: %v", err)
				}
				return "", fmt.Errorf("账号或密码错误")
			}
			if response.ErrInfo != "" {
				if err := updateAccountInvalid(account.ID); err != nil {
					log.Printf("标记账号不可用失败: %v", err)
				}
				return "", fmt.Errorf(response.ErrInfo)
			} else {
				if err := updateAccountNeedVerify(account.ID); err != nil {
					log.Printf("标记账号需要验证失败: %v", err)
				}
				return "", fmt.Errorf("该账号需要手机号登录验证")
			}
		} else {
			return "", fmt.Errorf("登录响应不包含成功跳转信息")
		}
	}
	// 提取Cookie
	cookies := resp.Header.Get("Set-Cookie")
	if cookies == "" {
		return "", fmt.Errorf("登录成功但未获取到Cookie")
	}
	log.Printf("登录成功，用户: %s", account.Username)
	return cookies, nil
}

// 获取商品列表通过店铺ID
func outGetGoodsListMsgByShopId(shopId int, proxy string, isImage int, sortType string, sort string, priceMin float32, priceMax float32, pageNum, returnNum int) (books []BookInfo, goodsNum string, pNum string, err error) {
	// 判断店铺ID
	if shopId == 0 {
		return nil, "", "", fmt.Errorf("店铺编码为空!")
	}
	// 判断是否有图片，设置默认值0
	var isImageStr string
	if isImage == 0 {
		isImageStr = "0"
	} else {
		isImageStr = "1"
	}
	// 判断一页图书数量，设置默认值100
	if returnNum == 0 {
		returnNum = 100
	}
	// 判断页数，设置默认值1
	if pageNum == 0 {
		pageNum = 1
	}
	// 判断排序类型，设置默认值sort
	if sortType == "" {
		sortType = "sort"
	} else {
		validSortTypes := map[string]bool{
			"sort":    true,
			"putDate": true,
			"newItem": true,
			"price":   true,
		}
		if !validSortTypes[sortType] {
			return nil, "", "", fmt.Errorf("无效的排序类型: %s，可选值: sort, putDate, newItem, price", sortType)
		}
	}
	// 判断排序，设置默认值desc
	if sort == "" {
		sort = "desc"
	} else {
		validSorts := map[string]bool{
			"desc": true,
			"asc":  true,
		}
		if !validSorts[sort] {
			return nil, "", "", fmt.Errorf("无效的排序类型: %s，可选值: desc, asc", sort)
		}
	}
	var url string
	var pMin int
	pMin = 0
	var pMax int
	pMax = 0
	// 判断价格下限，设置默认值0
	if priceMin == 0 && priceMax == 0 {
		// 调用的url
		url = fmt.Sprintf("https://shop.kongfz.com/%d/all/%s_%d_0_0_%d_%s_%s_%d_%d",
			shopId, isImageStr, returnNum, pageNum, sortType, sort, pMin, pMax)
	} else if priceMin == 0 {
		url = fmt.Sprintf("https://shop.kongfz.com/%d/all/%s_%d_0_0_%d_%s_%s_%d_%.2f",
			shopId, isImageStr, returnNum, pageNum, sortType, sort, pMin, priceMax)
	} else if priceMax == 0 {
		url = fmt.Sprintf("https://shop.kongfz.com/%d/all/%s_%d_0_0_%d_%s_%s_%.2f_%d",
			shopId, isImageStr, returnNum, pageNum, sortType, sort, priceMin, pMax)
	} else {
		url = fmt.Sprintf("https://shop.kongfz.com/%d/all/%s_%d_0_0_%d_%s_%s_%.2f_%.2f",
			shopId, isImageStr, returnNum, pageNum, sortType, sort, priceMin, priceMax)
	}
	// 发送请求
	response, err := fetchResponse(url, proxy)
	if err != nil {
		return nil, "", "", err
	}
	body, err := io.ReadAll(response.Body)
	if err != nil {
		return nil, "", "", err
	}
	doc, err := goquery.NewDocumentFromReader(strings.NewReader(string(body)))
	// 全部商品数量
	num := doc.Find("div.crumbs-nav-main.clearfix").Find("span")
	if match := regexp.MustCompile(`\d+`).FindString(num.Text()); match != "" {
		goodsNum = match
	}
	// 商品页数
	pg := doc.Find("li.pull-right.page_num").Find("span")
	_, split, found := strings.Cut(strings.TrimSpace(pg.Text()), "/")
	if found {
		pNum = split
	} else {
		log.Printf("未找到页数！")
	}
	infoDiv := doc.Find("div.list-content")
	if infoDiv.Length() > 0 {
		item := infoDiv.Find("div.item.clearfix")
		for i := 0; i < item.Length(); i++ {
			s := item.Eq(i)
			book := BookInfo{}
			// 书名
			book.BookName = strings.TrimSpace(s.Find("div.title a.link").Text())
			// 提取ISBN
			book.ISBN = strings.TrimSpace(s.AttrOr("isbn", ""))
			// 店铺ID
			shopid, _ := strconv.Atoi(strings.TrimSpace(s.AttrOr("shopid", "")))
			book.ShopId = int64(shopid)
			// 商品ID
			itemid, _ := strconv.Atoi(strings.TrimSpace(s.AttrOr("itemid", "")))
			book.ItemId = int64(itemid)
			book.DetailUrl = s.Find("div.item-img a.img-box").AttrOr("href", "")
			books = append(books, book)
		}
	}
	return books, goodsNum, pNum, nil
}

// 获取商品信息通过商品详情链接
func outGetGoodsMsgByDetailUrl(detailUrl, proxy string) (*BookInfo, error) {
	response, err := fetchResponse(detailUrl, proxy)
	if err != nil {
		return nil, err
	}
	body, err := io.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	// 解析HTML文档
	document, err := goquery.NewDocumentFromReader(strings.NewReader(string(body)))
	if err != nil {
		return nil, err
	}
	// 获取商品信息的快递费
	fee, err := getBookDetailShippingFee(detailUrl, proxy)
	if err != nil {
		return nil, err
	}
	book := BookInfo{}
	//书名
	book.BookName = strings.TrimSpace(document.Find("h1.title").Text())
	//作者等信息
	topDiv := document.Find("div.keywords-define.keywords-define-1000.clear-fix")
	if topDiv.Length() > 0 {
		topDiv.Find("li").Each(func(i int, li *goquery.Selection) {
			titleSpan := li.Find("span.keywords-define-title")
			contentSpan := li.Find("span.keywords-define-txt")
			if contentSpan.Length() == 0 {
				fmt.Printf("未找到指定的contentSpan信息")
			}
			titleText := strings.TrimSpace(titleSpan.Text())
			contentText := strings.TrimSpace(contentSpan.Text())
			titleText = strings.TrimSpace(titleText)
			if strings.Contains(titleText, "作者") {
				book.Author = cleanString(contentText)
			}
			if strings.Contains(titleText, "出版社") {
				book.Publisher = contentText
			}
			if strings.Contains(titleText, "出版人") {
				book.Publisher = contentText
			}
			if strings.Contains(titleText, "ISBN") {
				book.ISBN = contentText
			}
			if strings.Contains(titleText, "出版时间") {
				book.PublicationTime = validateDateFormat(contentText)
			}
			if strings.Contains(titleText, "版次") {
				book.Edition = contentText
			}
			if strings.Contains(titleText, "装帧") {
				book.BindingLayout = contentText
			}
			if strings.Contains(titleText, "开本") {
				book.Format = contentText
			}
			if strings.Contains(titleText, "页数") {
				book.Pages = contentText
			}
			if strings.Contains(titleText, "字数") {
				book.Wordage = contentText
			}
			if strings.Contains(titleText, "纸张") {
				book.Paper = contentText
			}
			if strings.Contains(titleText, "年代") {
				book.Era = contentText
			}
			if strings.Contains(titleText, "刻印方式") {
				book.EngravingMethod = contentText
			}
			if strings.Contains(titleText, "尺寸") {
				book.Dimensions = contentText
			}
			if strings.Contains(titleText, "册数") {
				book.VolumeNumber = contentText
			}
		})
	} else {
		botDiv := document.Find("div.detail-lists.clear-fix")
		botDiv.Find("li").Each(func(i int, li *goquery.Selection) {
			spanText := strings.TrimSpace(li.Find("span").Text())
			spanText = strings.TrimSpace(spanText)
			if strings.Contains(li.Text(), "作者") {
				book.Author = cleanString(li.Text())
				book.Author = strings.ReplaceAll(book.Author, "作者:", "")
				book.Author = strings.ReplaceAll(book.Author, "著", "")
			}
			if strings.Contains(li.Text(), "出版社") {
				book.Publisher = spanText
			}
			if strings.Contains(li.Text(), "出版时间") {
				book.PublicationTime = validateDateFormat(spanText)
			}
			if strings.Contains(li.Text(), "ISBN") {
				book.ISBN = spanText
			}
			if strings.Contains(li.Text(), "装帧") {
				book.BindingLayout = spanText
			}
			if strings.Contains(li.Text(), "开本") {
				book.Format = spanText
			}
			if strings.Contains(li.Text(), "纸张") {
				book.Paper = spanText
			}
			if strings.Contains(li.Text(), "版次") {
				book.Edition = spanText
			}
			if strings.Contains(li.Text(), "页数") {
				book.Pages = spanText
			}
			if strings.Contains(li.Text(), "字数") {
				book.Wordage = spanText
			}
		})
	}

	//图片
	var imgUrls []string
	tpUl := document.Find("ul.lg-list")
	tpUl.Find("img").Each(func(i int, s *goquery.Selection) {
		dataImgUrl, exists := s.Attr("data-imgurl")
		if exists && dataImgUrl != "" {
			imgUrls = append(imgUrls, dataImgUrl)
		}
	})
	book.BookPicS = strings.Join(imgUrls, ",")
	// 售价
	price := document.Find("i.now-price-text").Text()
	priceN := regexp.MustCompile(`(\d+\.?\d*)`)
	if match := priceN.FindStringSubmatch(price); len(match) > 0 {
		book.SellingPrice = match[1]
	}
	// 定价价
	fixPrice := document.Find("span.origin-price-text.clearfix").Text()
	fixPriceN := regexp.MustCompile(`(\d+\.?\d*)`)
	if match := fixPriceN.FindStringSubmatch(fixPrice); len(match) > 0 {
		book.FixPrice = match[1]
	}
	// 品相
	text := document.Find("span.quality-text-cot.clearfix i").Text()
	book.Condition = strings.TrimSpace(text)
	// 快递费
	book.ExpressDeliveryFee = fee
	return &book, nil
}

// 获取商品信息的快递费(定位到河南)
func getBookDetailShippingFee(url, proxy string) (string, error) {
	compile := regexp.MustCompile(`kongfz\.com/(\d+)/(\d+)`)
	match := compile.FindStringSubmatch(url)
	var shippingFee string
	var shopId int
	var itemId int
	if len(match) == 3 {
		firstNum, err := strconv.Atoi(match[1]) // 店铺ID
		if err != nil {
			return "", fmt.Errorf("无效的店铺编码: %s", match[1])
		}
		shopId = firstNum
		secondNum, err := strconv.Atoi(match[2]) // 图书ID
		if err != nil {
			return "", fmt.Errorf("无效的图书编码: %s", match[2])
		}
		itemId = secondNum
	}
	shippingFeeUrl := fmt.Sprintf("https://book.kongfz.com/store-web/pc/v1/mould/calculateFee?area=13003000000&itemId=%d&shopId=%d", itemId, shopId)
	// 创建HTTP客户端
	request := gorequest.New()
	// 设置代理（如果有提供代理URL）
	if proxy != "" {
		request.Proxy(proxy)
	}
	// 设置超时和其他配置
	request.Timeout(30 * time.Second)
	// 发送请求
	resp, body, errs := request.Get(shippingFeeUrl).
		Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
		Set("Accept", "application/json, text/plain, */*").
		Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
		End()
	// 错误处理
	if len(errs) > 0 {
		return "", fmt.Errorf("请求失败: %v", errs)
	}
	// 检查HTTP状态码
	if resp.StatusCode != http.StatusOK {
		return "", fmt.Errorf("HTTP错误: %s", resp.Status)
	}
	calculateFee := struct {
		ErrCode    int    `json:"errCode"`
		ErrMessage string `json:"errMessage"`
		Result     struct {
			FeeList []struct {
				FreeCondition string `json:"freeCondition"`
				ShippingID    string `json:"shippingId"`
				ShippingName  string `json:"shippingName"`
				ShippingValue string `json:"shippingValue"`
			} `json:"feeList"`
			FeeText string `json:"feeText"`
		} `json:"result"`
		Status bool `json:"status"`
	}{}

	err := json.Unmarshal([]byte(body), &calculateFee)
	if err != nil {
		return "", fmt.Errorf("解析JSON失败: %v", err)
	}
	for _, fee := range calculateFee.Result.FeeList {
		shippingFee = fee.ShippingValue
	}
	return shippingFee, nil
}

// 公用发送请求方法
func fetchResponse(url, proxy string) (*http.Response, error) {
	log.Printf("调用的URL: %s", url)
	maxRetries := cf.App.MaxRetryTimes
	var detailsResp *http.Response
	var errors []error
	for attempt := 0; attempt < maxRetries; attempt++ {
		if attempt > 0 {
			log.Printf("第 %d 次重试请求...", attempt)
			// 重试前等待，使用指数退避策略
			waitTime := time.Duration(attempt*attempt) * cf.App.RateLimitDelay // 平方退避
			log.Printf("等待 %v 后重试", waitTime)
			time.Sleep(waitTime)
		}
		if proxy != "" {
			detailsResp, _, errors = gorequest.New().
				Get(url).
				Proxy(proxy).
				Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36").
				Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8").
				Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
				Timeout(120 * time.Second).
				End()
		}
		if proxy == "" {
			detailsResp, _, errors = gorequest.New().
				Get(url).
				Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36").
				Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8").
				Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
				Timeout(120 * time.Second).
				End()
		}
		// 检查是否需要重试
		shouldRetry := false
		if len(errors) > 0 {
			shouldRetry = true
			log.Printf("请求失败 (尝试 %d/%d): %v", attempt+1, maxRetries+1, errors)
		} else if detailsResp == nil {
			shouldRetry = true
			log.Printf("响应为空 (尝试 %d/%d)", attempt+1, maxRetries+1)
		} else if detailsResp.StatusCode != http.StatusOK {
			// 只对服务器错误进行重试，不对客户端错误重试
			if detailsResp.StatusCode >= 500 {
				shouldRetry = true
			}
			log.Printf("HTTP状态码: %d,HTTP请求失败: %s (尝试 %d/%d)", detailsResp.StatusCode, detailsResp.Body, attempt+1, maxRetries+1)
		}
		// 如果不需要重试，跳出循环
		if !shouldRetry {
			break
		}
		// 如果是最后一次尝试，不继续重试
		if attempt == maxRetries {
			break
		}
		// 关闭响应体（如果存在）
		if detailsResp != nil && detailsResp.Body != nil {
			detailsResp.Body.Close()
		}
	}
	// 检测请求是否错误
	if len(errors) > 0 {
		var proxyAuthFailed bool
		var timeoutError bool
		var connectionError bool
		for _, e := range errors {
			errStr := e.Error()
			if strings.Contains(errStr, "Proxy Authentication Required") {
				proxyAuthFailed = true
			}
			if strings.Contains(errStr, "timeout") || strings.Contains(errStr, "i/o timeout") {
				timeoutError = true
			}
			if strings.Contains(errStr, "connection") || strings.Contains(errStr, "connect") {
				connectionError = true
			}
		}
		if proxyAuthFailed {
			return nil, fmt.Errorf("代理认证失败")
		}
		if timeoutError {
			return nil, fmt.Errorf("请求超时，经过 %d 次尝试，超时网址:%s", maxRetries+1, url)
		}
		if connectionError {
			return nil, fmt.Errorf("网络连接错误，经过 %d 次尝试，错误网址:%s", maxRetries+1, url)
		}
		return nil, fmt.Errorf("查询请求失败，经过 %d 次尝试: %v，失败网址:%s", maxRetries+1, errors, url)
	}
	if detailsResp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("HTTP错误: %s", detailsResp.Status)
	}
	return detailsResp, nil
}

// 获取销量榜商品列表(带有Out的都非官放标准接口)
func outGetTopGoodsListMsg(catId int, proxy string) ([]string, error) {
	// 构建请求URL
	url := fmt.Sprintf("https://item.kongfz.com/api/pc/getSellWellListDetail?page=1&pageSize=100&timeRank=2&catId=%d", catId)
	// 创建HTTP客户端
	request := gorequest.New()
	// 设置代理（如果有提供代理URL）
	if proxy != "" {
		request.Proxy(proxy)
	}
	// 设置超时和其他配置
	request.Timeout(30 * time.Second)
	// 发送请求
	resp, body, errs := request.Get(url).
		Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
		Set("Accept", "application/json, text/plain, */*").
		Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
		Set("Referer", "https://item.kongfz.com/").
		End()
	// 错误处理
	if len(errs) > 0 {
		return nil, fmt.Errorf("请求失败: %v", errs)
	}
	// 检查HTTP状态码
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("HTTP错误: %s", resp.Status)
	}
	var bookDetailResponse BookDetailResponse
	err := json.Unmarshal([]byte(body), &bookDetailResponse)
	if err != nil {
		return nil, fmt.Errorf("解析JSON失败: %v", err)
	}
	if !bookDetailResponse.Status {
		return nil, fmt.Errorf("API返回错误: %s (代码: %d)", bookDetailResponse.ErrMessage, bookDetailResponse.ErrCode)
	}

	var isbnList []string
	for _, item := range bookDetailResponse.Result.Data {
		if item.Isbn != "" {
			isbnList = append(isbnList, item.Isbn)
		}
	}
	isbnList = removeDuplicateISBNs(isbnList)
	return isbnList, nil
}

// 去除重复的ISBN
func removeDuplicateISBNs(isbns []string) []string {
	seen := make(map[string]bool)
	var result []string
	for _, isbn := range isbns {
		if !seen[isbn] {
			seen[isbn] = true
			result = append(result, isbn)
		}
	}
	return result
}

// 获取Document文档(带重试机制)
func fetchDocument(fetchMode, proxyType, username, password, machineCode, url string) (*goquery.Document, error) {
	log.Printf("调用的URL: %s", url)
	maxRetries := cf.App.MaxRetryTimes
	var detailsResp *http.Response
	var errors []error
	var detailsBody []byte
	for attempt := 0; attempt < maxRetries; attempt++ {
		if attempt > 0 {
			log.Printf("第 %d 次重试请求...", attempt)
			// 重试前等待，使用指数退避策略
			waitTime := time.Duration(attempt*attempt) * cf.App.RateLimitDelay // 平方退避
			log.Printf("等待 %v 后重试", waitTime)
			time.Sleep(waitTime)
		}
		if fetchMode == NotProxy {
			detailsResp, _, errors = gorequest.New().
				Get(url).
				Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36").
				Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8").
				Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
				Timeout(120 * time.Second).
				End()
		} else if fetchMode == UseProxy {
			detailsReq := XxProxyRequest(proxyType, username, password, machineCode).
				Get(url).
				Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36").
				Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8").
				Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
				Set("Connection", "close") // 每次请求关闭连接
			detailsResp, _, errors = detailsReq.End()
		} else {
			errors = append(errors, fmt.Errorf("请求失败，选择模式错误！"))
		}
		// 检查是否需要重试
		shouldRetry := false
		if len(errors) > 0 {
			shouldRetry = true
			log.Printf("请求失败 (尝试 %d/%d): %v", attempt+1, maxRetries+1, errors)
		} else if detailsResp == nil {
			shouldRetry = true
			log.Printf("响应为空 (尝试 %d/%d)", attempt+1, maxRetries+1)
		} else if detailsResp.StatusCode != http.StatusOK {
			// 只对服务器错误进行重试，不对客户端错误重试
			if detailsResp.StatusCode >= 500 {
				shouldRetry = true
			}
			log.Printf("HTTP状态码: %d,HTTP请求失败: %s (尝试 %d/%d)", detailsResp.StatusCode, detailsResp.Body, attempt+1, maxRetries+1)
		}
		// 如果不需要重试，跳出循环
		if !shouldRetry {
			break
		}
		// 如果是最后一次尝试，不继续重试
		if attempt == maxRetries {
			break
		}
		// 关闭响应体（如果存在）
		if detailsResp != nil && detailsResp.Body != nil {
			detailsResp.Body.Close()
		}
	}
	// 检测请求是否错误
	if len(errors) > 0 {
		var proxyAuthFailed bool
		var timeoutError bool
		var connectionError bool
		for _, e := range errors {
			errStr := e.Error()
			if strings.Contains(errStr, "Proxy Authentication Required") {
				proxyAuthFailed = true
			}
			if strings.Contains(errStr, "timeout") || strings.Contains(errStr, "i/o timeout") {
				timeoutError = true
			}
			if strings.Contains(errStr, "connection") || strings.Contains(errStr, "connect") {
				connectionError = true
			}
		}
		if proxyAuthFailed {
			return nil, fmt.Errorf("代理认证失败")
		}
		if timeoutError {
			return nil, fmt.Errorf("请求超时，经过 %d 次尝试，超时网址:%s", maxRetries+1, url)
		}
		if connectionError {
			return nil, fmt.Errorf("网络连接错误，经过 %d 次尝试，错误网址:%s", maxRetries+1, url)
		}
		return nil, fmt.Errorf("查询请求失败，经过 %d 次尝试: %v，失败网址:%s", maxRetries+1, errors, url)
	}
	if detailsResp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("HTTP错误: %s", detailsResp.Status)
	}

	detailsBody, err := io.ReadAll(detailsResp.Body)
	if err != nil {
		return nil, err
	}

	return goquery.NewDocumentFromReader(strings.NewReader(string(detailsBody)))
}

// 合并基本信息和详情
func mergeBookDetails(bookItems []BookItem, detailResults map[string]*DetailResult) []BookInfo {
	var books []BookInfo

	for _, item := range bookItems {
		book := item.Book

		// 如果有详情且获取成功，补充详细信息
		if item.HasDetail && item.DetailURL != "" {
			if result, exists := detailResults[item.DetailURL]; exists && result.Error == nil && result.Doc != nil {
				detailsDiv := result.Doc.Find("div.detail-lists.clear-fix")
				if detailsDiv.Length() > 0 {
					selection := detailsDiv.Find("li")
					book.Author = extractNormalDetails(selection, "作者")
					book.Publisher = extractNormalDetails(selection, "出版社")
					detailsTime := extractNormalDetails(selection, "出版时间")
					if detailsTime != "" {
						formats := []string{"2006-01", "2006-01-02", "2006"}
						for _, format := range formats {
							if t, err := time.Parse(format, detailsTime); err == nil {
								book.PublicationTime = t.Unix()
								break
							}
						}
					}
					book.ISBN = extractNormalDetails(selection, "ISBN")
					book.Edition = extractNormalDetails(selection, "版次")
					book.FixPrice = extractNormalDetails(selection, "定价")
					book.BindingLayout = extractNormalDetails(selection, "装帧")
					book.Format = extractNormalDetails(selection, "开本")
					book.Pages = extractNormalDetails(selection, "页数")
					book.Wordage = extractNormalDetails(selection, "字数")
				}
			}
		}

		books = append(books, book)
	}
	return books
}

// 根据url获取单个图书详情信息
func getUrlBookDetails(fetchMode, proxyType, username, password, machineCode, url string) (books []BookInfo, err error) {
	document, err := fetchDocument(fetchMode, proxyType, username, password, machineCode, url)
	if err != nil {
		return nil, err
	}

	fee, err := FetchBookDetailsShippingFee(url)
	if err != nil {
		return nil, err
	}
	book := BookInfo{}
	//书名
	book.BookName = strings.TrimSpace(document.Find("h1.title").Text())

	//作者等信息
	topDiv := document.Find("div.keywords-define.keywords-define-1000.clear-fix")
	if topDiv.Length() > 0 {
		topDiv.Find("li").Each(func(i int, li *goquery.Selection) {
			titleSpan := li.Find("span.keywords-define-title")
			contentSpan := li.Find("span.keywords-define-txt")
			if contentSpan.Length() == 0 {
				fmt.Printf("未找到指定的contentSpan信息")
			}
			titleText := strings.TrimSpace(titleSpan.Text())
			contentText := strings.TrimSpace(contentSpan.Text())
			titleText = strings.TrimSpace(titleText)
			if strings.Contains(titleText, "作者") {
				book.Author = cleanString(contentText)
			}
			if strings.Contains(titleText, "出版社") {
				book.Publisher = contentText
			}
			if strings.Contains(titleText, "出版人") {
				book.Publisher = contentText
			}
			if strings.Contains(titleText, "ISBN") {
				book.ISBN = contentText
			}
			if strings.Contains(titleText, "出版时间") {
				book.PublicationTime = validateDateFormat(contentText)
			}
			if strings.Contains(titleText, "版次") {
				book.Edition = contentText
			}
			if strings.Contains(titleText, "装帧") {
				book.BindingLayout = contentText
			}
			if strings.Contains(titleText, "开本") {
				book.Format = contentText
			}
			if strings.Contains(titleText, "页数") {
				book.Pages = contentText
			}
			if strings.Contains(titleText, "字数") {
				book.Wordage = contentText
			}
			if strings.Contains(titleText, "纸张") {
				book.Paper = contentText
			}
			if strings.Contains(titleText, "年代") {
				book.Era = contentText
			}
			if strings.Contains(titleText, "刻印方式") {
				book.EngravingMethod = contentText
			}
			if strings.Contains(titleText, "尺寸") {
				book.Dimensions = contentText
			}
			if strings.Contains(titleText, "册数") {
				book.VolumeNumber = contentText
			}
		})
	} else {
		botDiv := document.Find("div.detail-lists.clear-fix")
		botDiv.Find("li").Each(func(i int, li *goquery.Selection) {
			spanText := strings.TrimSpace(li.Find("span").Text())
			spanText = strings.TrimSpace(spanText)
			if strings.Contains(li.Text(), "作者") {
				book.Author = cleanString(li.Text())
				book.Author = strings.ReplaceAll(book.Author, "作者:", "")
				book.Author = strings.ReplaceAll(book.Author, "著", "")
			}
			if strings.Contains(li.Text(), "出版社") {
				book.Publisher = spanText
			}
			if strings.Contains(li.Text(), "出版时间") {
				book.PublicationTime = validateDateFormat(spanText)
			}
			if strings.Contains(li.Text(), "ISBN") {
				book.ISBN = spanText
			}
			if strings.Contains(li.Text(), "装帧") {
				book.BindingLayout = spanText
			}
			if strings.Contains(li.Text(), "开本") {
				book.Format = spanText
			}
			if strings.Contains(li.Text(), "纸张") {
				book.Paper = spanText
			}
			if strings.Contains(li.Text(), "版次") {
				book.Edition = spanText
			}
			if strings.Contains(li.Text(), "页数") {
				book.Pages = spanText
			}
			if strings.Contains(li.Text(), "字数") {
				book.Wordage = spanText
			}
		})
	}

	//图片
	var imgUrls []string
	tpUl := document.Find("ul.lg-list")
	tpUl.Find("img").Each(func(i int, s *goquery.Selection) {
		dataImgUrl, exists := s.Attr("data-imgurl")
		if exists && dataImgUrl != "" {
			imgUrls = append(imgUrls, dataImgUrl)
		}
	})
	book.BookPicS = strings.Join(imgUrls, ",")
	// 售价
	price := document.Find("i.now-price-text").Text()
	priceN := regexp.MustCompile(`(\d+\.?\d*)`)
	if match := priceN.FindStringSubmatch(price); len(match) > 0 {
		book.SellingPrice = match[1]
	}
	// 定价价
	fixPrice := document.Find("span.origin-price-text.clearfix").Text()
	fixPriceN := regexp.MustCompile(`(\d+\.?\d*)`)
	if match := fixPriceN.FindStringSubmatch(fixPrice); len(match) > 0 {
		book.FixPrice = match[1]
	}
	// 品相
	text := document.Find("span.quality-text-cot.clearfix i").Text()
	book.Condition = strings.TrimSpace(text)
	// 快递费
	if fee != "" {
		if fee == "包邮" {
			book.ExpressDeliveryFee = "0"
		} else {
			book.ExpressDeliveryFee = fee
		}
	}
	books = append(books, book)
	return books, nil
}

// 获取店铺页面的所有快递费用
func FetchProductInfoWithChromedp(url string) (*ProductResponse, error) {
	// 创建上下文
	opts := append(chromedp.DefaultExecAllocatorOptions[:],
		chromedp.Flag("headless", true),
		chromedp.Flag("disable-gpu", true),
		chromedp.Flag("no-sandbox", true),
		chromedp.Flag("disable-dev-shm-usage", true),
		chromedp.UserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"),
		// 禁用图片加载，加快速度
		chromedp.Flag("blink-settings", "imagesEnabled=false"),
	)
	// 启动浏览器
	allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
	defer cancel()
	// 创建浏览器上下文
	ctx, cancel := chromedp.NewContext(allocCtx)
	defer cancel()
	// 设置超时
	ctx, cancel = context.WithTimeout(ctx, 60*time.Second)
	defer cancel()
	log.Printf("[CHROMEDP] 开始导航到URL: %s", url)
	// 第一步：先导航到页面并等待完全加载
	err := chromedp.Run(ctx,
		// 导航到目标页面
		chromedp.Navigate(url),

		// 等待页面初步加载
		chromedp.WaitReady("body", chromedp.ByQuery),
		chromedp.Sleep(3*time.Second),

		// 第二步：刷新页面，重新加载动态内容
		chromedp.Reload(),

		// 等待刷新后页面加载
		chromedp.WaitReady("body", chromedp.ByQuery),
		chromedp.Sleep(5*time.Second),

		// 等待关键元素出现
		chromedp.WaitVisible(".item.clearfix", chromedp.ByQuery),

		// 滚动页面以触发动态加载
		chromedp.Evaluate(`window.scrollTo(0, document.body.scrollHeight / 3)`, nil),
		chromedp.Sleep(2*time.Second),
		chromedp.Evaluate(`window.scrollTo(0, document.body.scrollHeight / 2)`, nil),
		chromedp.Sleep(2*time.Second),
		chromedp.Evaluate(`window.scrollTo(0, document.body.scrollHeight)`, nil),
		chromedp.Sleep(3*time.Second),
		chromedp.Evaluate(`window.scrollTo(0, 0)`, nil),
		chromedp.Sleep(1*time.Second),
	)
	if err != nil {
		log.Printf("[CHROMEDP] 页面导航失败: %v", err)
		return nil, fmt.Errorf("页面导航失败: %v", err)
	}
	log.Printf("[CHROMEDP] 页面导航完成，开始提取数据")
	var evalResult map[string]interface{}
	// 执行任务
	err = chromedp.Run(ctx,
		// 导航到目标页面
		chromedp.Navigate(url),

		// 执行 JavaScript 来提取商品信息
		chromedp.Evaluate(`(function() {
			console.log("开始提取商品信息...");
			try {
				let productData = [];
				// 查找所有商品项 - 针对孔夫子旧书网的特定选择器
				const itemSelectors = [
					'.item.clearfix',
					'.list-item',
					'.product-item',
					'.goods-item',
					'[class*="item"]'
				];
				let items = [];
				for (let selector of itemSelectors) {
					const found = document.querySelectorAll(selector);
					if (found.length > 0) {
						items = found;
						console.log("使用选择器:", selector, "找到项目数:", items.length);
						break;
					}
				}

				if (items.length === 0) {
					// 如果没有找到特定选择器，尝试查找任何看起来像商品的项目
					items = document.querySelectorAll('div[class*="item"], li[class*="item"]');
					console.log("使用通用选择器找到项目数:", items.length);
				}
				console.log("总共找到商品项:", items.length);
				// 遍历每个商品项
				items.forEach((item, index) => {
					// 提取 itemid
					let itemId = '';

					// 方法1: 从元素属性获取
					if (item.hasAttribute('itemid')) {
						itemId = item.getAttribute('itemid');
					}

					// 方法2: 从数据属性获取
					if (!itemId && item.hasAttribute('data-itemid')) {
						itemId = item.getAttribute('data-itemid');
					}

					// 方法3: 从ID属性获取
					if (!itemId && item.hasAttribute('id')) {
						const id = item.getAttribute('id');
						if (id.includes('item') || id.includes('product')) {
							itemId = id;
						}
					}

					// 方法4: 从链接中提取itemid
					if (!itemId) {
						const links = item.querySelectorAll('a[href*="item"], a[href*="product"]');
						for (let link of links) {
							const href = link.getAttribute('href');
							if (href) {
								const itemMatch = href.match(/(?:item|product)[_-]?(\d+)/i);
								if (itemMatch) {
									itemId = itemMatch[1];
									break;
								}
							}
						}
					}

					// 方法5: 从子元素中查找itemid
					if (!itemId) {
						const childWithItemId = item.querySelector('[itemid], [data-itemid]');
						if (childWithItemId) {
							if (childWithItemId.hasAttribute('itemid')) {
								itemId = childWithItemId.getAttribute('itemid');
							} else if (childWithItemId.hasAttribute('data-itemid')) {
								itemId = childWithItemId.getAttribute('data-itemid');
							}
						}
					}

					// 提取书名
					let bookName = '';
					const titleSelectors = [
						'.title a',
						'.book-title',
						'.item-title',
						'.name a',
						'h3 a',
						'h4 a',
						'.link',
						'a[title]'
					];

					for (let selector of titleSelectors) {
						const titleEl = item.querySelector(selector);
						if (titleEl) {
							bookName = titleEl.textContent.trim();
							if (bookName && bookName.length > 1) {
								break;
							}
						}
					}

					// 如果没找到，尝试在item内查找任何文本作为书名
					if (!bookName) {
						const textContent = item.textContent;
						// 尝试提取看起来像书名的文本（较长的文本块）
						const lines = textContent.split('\n').map(line => line.trim()).filter(line => line.length > 5);
						if (lines.length > 0) {
							bookName = lines[0];
						}
					}

					// 提取价格
					let price = '';
					const priceSelectors = [
						'.price span',
						'.price .bold',
						'.current-price',
						'.sell-price',
						'.cost',
						'.money',
						'[class*="price"]',
						'strong'
					];

					for (let selector of priceSelectors) {
						const priceEl = item.querySelector(selector);
						if (priceEl) {
							let priceText = priceEl.textContent.trim();
							// 清理价格文本，保留数字和小数点
							priceText = priceText.replace(/[^\d\.]/g, '');
							if (priceText && !isNaN(parseFloat(priceText))) {
								price = '¥' + priceText;
								break;
							}
						}
					}

					// 如果没找到价格，尝试在文本中查找价格模式
					if (!price) {
						const itemText = item.textContent;
						const priceMatch = itemText.match(/[¥￥]?\s*(\d+\.?\d*)/);
						if (priceMatch) {
							price = '¥' + priceMatch[1];
						}
					}

					// 提取快递费用
					let shippingFee = '';
					const shippingSelectors = [
						'.ship-fee',
						'.shipping-fee',
						'.express-fee',
						'.freight',
						'.postage',
						'[class*="fee"]',
						'[class*="快递"]',
						'[class*="运费"]'
					];

					for (let selector of shippingSelectors) {
						const shippingEl = item.querySelector(selector);
						if (shippingEl) {
							shippingFee = shippingEl.textContent.trim();
							if (shippingFee) break;
						}
					}

					// 如果没找到运费元素，尝试在文本中查找运费关键词
					if (!shippingFee) {
						const itemText = item.textContent;
						const feeMatches = itemText.match(/(运费[：:]\s*[^\s\n]+)|(快递[：:]\s*[^\s\n]+)|(邮费[：:]\s*[^\s\n]+)/);
						if (feeMatches) {
							shippingFee = feeMatches[0];
						} else if (itemText.includes('包邮') || itemText.includes('免运费')) {
							shippingFee = '包邮';
						} else {
							shippingFee = '运费待确认';
						}
					}

					// 清理书名（移除过长的文本）
					if (bookName && bookName.length > 100) {
						bookName = bookName.substring(0, 100) + '...';
					}

					// 如果还没有itemid，生成一个基于索引的ID
					if (!itemId) {
						itemId = 'item_' + (index + 1);
					}

					// 添加到数据中
					productData.push({
						itemId: itemId,
						bookName: bookName || '商品${index + 1}',
						price: price || '价格待确认',
						shippingFee: shippingFee
					});
				});

				// 过滤掉明显无效的数据
				productData = productData.filter(item =>
					(item.bookName !== '商品1' || item.price !== '价格待确认') &&
					item.bookName && item.bookName.length > 0
				);

				console.log("处理后商品数量:", productData.length);
				if (productData.length > 0) {
					console.log("前3个商品示例:", productData.slice(0, 3));
				}

				return {
					success: true,
					message: "成功提取商品信息",
					data: productData
				};

			} catch(error) {
				console.error("提取商品信息时出错:", error);
				return {
					success: false,
					message: "提取商品信息时出错: " + error.message,
					data: []
				};
			}
		})()`, &evalResult),
	)

	if err != nil {
		return nil, fmt.Errorf("chromedp执行失败: %v", err)
	}

	// 处理 JavaScript 执行结果
	response := &ProductResponse{}

	// 转换结果数据
	if success, ok := evalResult["success"].(bool); ok {
		response.Success = success
	}
	if message, ok := evalResult["message"].(string); ok {
		response.Message = message
	}
	if data, ok := evalResult["data"].([]interface{}); ok {
		for _, item := range data {
			if productMap, ok := item.(map[string]interface{}); ok {
				product := ProductInfo{}
				if itemId, ok := productMap["itemId"].(string); ok {
					product.ItemID = itemId
				}
				if bookName, ok := productMap["bookName"].(string); ok {
					product.BookName = bookName
				}
				if price, ok := productMap["price"].(string); ok {
					product.Price = price
				}
				if shippingFee, ok := productMap["shippingFee"].(string); ok {
					info := extractShippingInfo(shippingFee)
					product.ShippingFee = info
				}
				response.Data = append(response.Data, product)
			}
		}
	}

	return response, nil
}

// 获取详情页的快递费用
func FetchBookDetailsShippingFee(url string) (string, error) {
	// 创建上下文
	opts := append(chromedp.DefaultExecAllocatorOptions[:],
		chromedp.Flag("headless", true),
		chromedp.Flag("disable-gpu", true),
		chromedp.Flag("no-sandbox", true),
		chromedp.Flag("disable-dev-shm-usage", true),
		chromedp.UserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"),
		// 禁用图片加载，加快速度
		chromedp.Flag("blink-settings", "imagesEnabled=false"),
	)
	// 启动浏览器
	allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
	defer cancel()
	// 创建浏览器上下文
	ctx, cancel := chromedp.NewContext(allocCtx)
	defer cancel()
	// 设置超时
	ctx, cancel = context.WithTimeout(ctx, 60*time.Second)
	defer cancel()
	log.Printf("[CHROMEDP] 开始导航到URL: %s", url)
	var result string

	// 增强的 JavaScript 脚本
	enhancedJSScript := `
		(function() {
			// 查找包含快递费用的元素
			const elements = document.querySelectorAll('*');
			let shippingFee = null;
			
			elements.forEach(element => {
				if (element.textContent.includes('快递￥')) {
					const match = element.textContent.match(/快递￥(\d+\.\d{2})/);
					if (match) {
						shippingFee = match[1];
						console.log('找到快递费用: ￥' + shippingFee);
					}
				}
				// 匹配格式2: 快递：包邮
				else if (element.textContent.includes('快递：包邮') || element.textContent.includes('快递:包邮')) {
					shippingFee = '包邮';
					console.log('找到快递费用: 包邮');
				}
				// 匹配格式3: 快递 包邮 (包含空格变体)
				else if (element.textContent.match(/快递[：:\s]包邮/)) {
					shippingFee = '包邮';
					console.log('找到快递费用: 包邮');
				}
			});
			
			if (!shippingFee) {
				// 如果没找到，尝试搜索整个页面
				const pageText = document.body.innerText;
				const match = pageText.match(/快递￥(\d+\.\d{2})/);
				if (match) {
					shippingFee = match[1];
					console.log('找到快递费用: ￥' + shippingFee);
				} 
				// 尝试匹配包邮
				else if (pageText.match(/快递[：:\s]包邮/)) {
					shippingFee = '包邮';
					console.log('找到快递费用: 包邮');
				}
				// 尝试其他包邮表述
				else if (pageText.includes('包邮') && pageText.includes('快递')) {
					shippingFee = '包邮';
					console.log('找到快递费用: 包邮');
				}
				else {
					console.log('未找到快递费用信息');
				}
			}
			return shippingFee;
		})();`
	// 先导航到页面并等待完全加载
	err := chromedp.Run(ctx,
		// 导航到目标页面
		chromedp.Navigate(url),
		// 刷新页面，重新加载动态内容
		chromedp.Reload(),
		// 等待刷新后页面加载
		chromedp.WaitReady("body", chromedp.ByQuery),
		chromedp.Sleep(8*time.Second),
		// 执行 JavaScript 来提取商品信息
		chromedp.Evaluate(enhancedJSScript, &result),
	)
	if err != nil {
		log.Printf("[CHROMEDP] 页面导航失败: %v", err)
		return "", fmt.Errorf("页面导航失败: %v", err)
	}
	log.Printf("[CHROMEDP] 页面导航完成，开始提取数据")

	if err != nil {
		return "", fmt.Errorf("chromedp执行失败: %v", err)
	}
	return result, nil
}

// 获取孔网实拍图(查询商品列表)
func getKFZSPTImageURL(proxyType, username, password, machineCode, isbn string) (*BookInfo, error) {
	log.Printf("[DEBUG] ", isbn, " 获取图书ISBN: %s", isbn)
	url := fmt.Sprintf("%s?dataType=0&keyword=%s&page=1&size=%d&sortType=7&actionPath=quality,sortType&quality=85~&quaSelect=2&userArea=13003000000", cf.API.ProductSearchURL, isbn, cf.App.Size)

	req := XxProxyRequest(proxyType, username, password, machineCode).
		Get(url).
		Set("User-Agent", cf.App.DefaultUserAgent).
		Set("Accept", "*/*")
	resp, body, errs := req.End()
	log.Printf("[DEBUG] 获取图书列表 URL: %s", url)

	// 只在有响应内容时才打印，避免日志过长
	if len(body) > 0 && len(body) < 500 {
		log.Printf("[DEBUG] 获取图书列表响应: %s", body)
	} else if len(body) > 0 {
		log.Printf("[DEBUG] 获取图书列表响应长度: %d 字符", len(body))
	} else {
		log.Printf("[DEBUG] 获取图书列表响应为空")
	}

	// 处理请求错误
	if len(errs) > 0 {
		// 检查是否是代理认证失败
		var proxyAuthFailed bool
		for _, e := range errs {
			if strings.Contains(e.Error(), "Proxy Authentication Required") {
				proxyAuthFailed = true
				break
			}
		}
		if proxyAuthFailed {
			return nil, fmt.Errorf("代理认证失败")
		}
		return nil, fmt.Errorf("查询请求失败: %v", errs)
	}

	// 检查HTTP状态码
	if resp.StatusCode != http.StatusOK {
		space := strings.TrimSpace(resp.Status)
		return nil, fmt.Errorf("HTTP错误: %s", space)
	}

	// 解析响应
	var apiResp struct {
		Status     int    `json:"status"`
		ErrType    string `json:"errType"`
		Message    string `json:"message"`
		SystemTime int64  `json:"systemTime"`
		Data       struct {
			ItemResponse struct {
				Total int `json:"total"`
				List  []struct {
					Title      string `json:"title"`
					ImgUrl     string `json:"imgUrl"`
					ImgBigUrl  string `json:"imgBigUrl"`
					ItemId     int64  `json:"itemId"`
					ShopId     int64  `json:"shopId"`
					TplRecords []struct {
						Key   string `json:"key"`
						Value string `json:"value"`
					} `json:"tplRecords"`
				} `json:"list"`
			} `json:"itemResponse"`
		} `json:"data"`
	}

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

	// 如果找到商品，返回图片URL
	if apiResp.Data.ItemResponse.Total > 0 && len(apiResp.Data.ItemResponse.List) > 0 {
		// 确定起始索引
		var startIndex int
		if cf.App.Size >= apiResp.Data.ItemResponse.Total {
			startIndex = apiResp.Data.ItemResponse.Total - 1
		} else {
			startIndex = cf.App.Size - 1
		}

		// 从指定索引开始，向前查找有效图片，最多重试3次
		for attempt := 0; attempt < 3; attempt++ {
			currentIndex := startIndex - attempt

			// 检查索引是否有效
			if currentIndex < 0 || currentIndex >= len(apiResp.Data.ItemResponse.List) {
				log.Printf("[DEBUG] 索引 %d 超出范围，跳过", currentIndex)
				continue
			}

			item := apiResp.Data.ItemResponse.List[currentIndex]

			// 检查图片URL是否存在
			if item.ImgBigUrl == "" {
				log.Printf("[DEBUG] 索引 %d 的图片URL为空，跳过", currentIndex)
				continue
			}

			info := &BookInfo{}
			info.BookName = item.Title
			info.BookPicS = item.ImgUrl
			info.ItemId = item.ItemId
			info.ShopId = item.ShopId

			// 安全地获取TplRecords中的值
			if len(item.TplRecords) > 0 {
				info.Author = item.TplRecords[0].Value
			}
			if len(item.TplRecords) > 1 {
				info.Publisher = item.TplRecords[1].Value
			}
			if len(item.TplRecords) > 2 {
				info.PublicationTime = validateDateFormat(item.TplRecords[2].Value)
			}
			if len(item.TplRecords) > 3 {
				info.BindingLayout = item.TplRecords[3].Value
			}

			// 成功时重置代理失败计数器
			resetProxyFailCount()
			return info, nil
		}
		// 如果所有尝试都失败了，返回错误
		log.Printf("[WARN] 经过3次尝试，未找到有效图片")
		return nil, fmt.Errorf("未找到有效图片，已尝试3次")
	}
	return nil, nil
}

// 获取孔网官图(查询图书条目)
func getKFZGTImageURL(proxyType, username, password, machineCode, isbn string) (*BookInfo, error) {
	url := fmt.Sprintf("%s?keyword=%s", cf.API.BookSearchURL, isbn)

	info := &BookInfo{}

	req := XxProxyRequest(proxyType, username, password, machineCode).
		Get(url).
		Set("User-Agent", cf.App.DefaultUserAgent).
		Set("Accept", "*/*")
	resp, body, errs := req.End()
	log.Printf("[DEBUG] 获取图书条目 URL: %s", url)
	// 只在有响应内容时才打印，避免日志过长
	if len(body) > 0 && len(body) < 500 {
		log.Printf("[DEBUG] 获取图书条目响应: %s", body)
	} else if len(body) > 0 {
		log.Printf("[DEBUG] 获取图书条目响应长度: %d 字符", len(body))
	} else {
		log.Printf("[DEBUG] 获取图书条目响应为空")
	}

	// 处理请求错误
	if len(errs) > 0 {
		// 检查是否是代理相关错误
		var isProxyError bool
		var errorDetails []string
		for _, e := range errs {
			errorStr := e.Error()
			errorDetails = append(errorDetails, errorStr)
			if strings.Contains(errorStr, "Proxy Authentication Required") ||
				strings.Contains(errorStr, "connectex: A connection attempt failed") ||
				strings.Contains(errorStr, "connectex: No connection could be made") ||
				strings.Contains(errorStr, "proxyconnect tcp") ||
				strings.Contains(errorStr, "timeout") ||
				strings.Contains(errorStr, "connection refused") {
				isProxyError = true
			}
		}

		log.Printf("[ERROR] 请求错误详情: %v", errorDetails)

		if isProxyError {
			// 处理代理失败
			return nil, fmt.Errorf("代理连接失败")
		}

		return nil, fmt.Errorf("查询请求失败: %v", errs)
	}

	//检查HTTP状态码
	if resp.StatusCode != http.StatusOK {
		space := strings.TrimSpace(resp.Status)
		return nil, fmt.Errorf("HTTP错误: %s", space)
	}

	// 解析响应
	var apiResp struct {
		Status     int    `json:"status"`
		ErrType    string `json:"errType"`
		Message    string `json:"message"`
		SystemTime int64  `json:"systemTime"`
		Data       struct {
			ItemResponse struct {
				Total int `json:"total"`
				List  []struct {
					BookName     string `json:"bookName"`
					Mid          int64  `json:"mid"`
					ImgUrlEntity struct {
						BigImgUrl string `json:"bigImgUrl"`
					} `json:"imgUrlEntity"`
					BookShowInfo []string `json:"bookShowInfo"`
				} `json:"list"`
			} `json:"itemResponse"`
		} `json:"data"`
	}

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

	// 如果找到条目，返回图片URL
	if apiResp.Data.ItemResponse.Total > 0 && len(apiResp.Data.ItemResponse.List) > 0 {
		list := apiResp.Data.ItemResponse.List[0]
		info := list.BookShowInfo

		bookItem := &BookInfo{
			BookName: list.BookName,
			BookPic:  list.ImgUrlEntity.BigImgUrl,
			Mid:      list.Mid,
		}

		// 根据长度安全填充字段
		if len(info) > 0 {
			bookItem.Author = info[0]
		}
		if len(info) > 1 {
			bookItem.Publisher = info[1]
		}
		if len(info) > 2 {
			bookItem.PublicationTime = validateDateFormat(info[2])
		}
		if len(info) > 3 {
			bookItem.BindingLayout = info[3]
		}
		if len(info) > 4 {
			bookItem.FixPrice = info[4]
		} else {
			log.Printf("[WARN] BookShowInfo 长度不足 (仅 %d 项): %v", len(info), info)
		}

		fmt.Println("bookItem: ", bookItem)
		return bookItem, nil
	}

	return info, nil
}

// 替换所有空白字符为空格
func cleanString(s string) string {
	s = strings.ReplaceAll(s, "\n", "")
	s = strings.ReplaceAll(s, "\r", "")
	s = strings.ReplaceAll(s, "\t", "")
	s = strings.ReplaceAll(s, " ", "")
	return removeDuplicates(s)
}

// 字符串去重
func removeDuplicates(s string) string {
	seen := make(map[rune]bool)
	var result strings.Builder
	for _, r := range s {
		if !seen[r] {
			seen[r] = true
			result.WriteRune(r)
		}
	}
	return result.String()
}

// 检测快递费用格式
func extractShippingInfo(shippingFee string) string {
	// 匹配 "快递￥数字" 格式
	re1 := regexp.MustCompile(`快递￥(\d+\.?\d*)`)
	// 匹配 "包邮" 格式
	re2 := regexp.MustCompile(`(包邮)`)

	if matches := re1.FindStringSubmatch(shippingFee); len(matches) > 1 {
		return matches[1] // 返回数字部分
	}

	if matches := re2.FindStringSubmatch(shippingFee); len(matches) > 1 {
		return "0" // 返回"包邮"
	}

	return ""
}

// 改进字段
func extractNormalDetails(s *goquery.Selection, fieldName string) string {
	var info string
	s.Each(func(i int, selection *goquery.Selection) {
		if strings.Contains(selection.Text(), fieldName) {
			all := strings.ReplaceAll(selection.Text(), "&nbsp;", "")
			all = strings.ReplaceAll(all, "\n", "")
			all = strings.ReplaceAll(all, " ", "")
			split := strings.SplitN(all, ":", 2)
			if len(split) > 1 {
				info = split[1]
			} else {
				return
			}
		}
	})
	return info
}

// 改进的字段提取函数
func extractNormalText(s *goquery.Selection, fieldName string) string {
	// 在左右两个分区中查找
	selectors := []string{"div.f_left", "div.f_right"}
	for _, selector := range selectors {
		fieldItem := s.Find(selector + " div.normal-item").FilterFunction(func(i int, sel *goquery.Selection) bool {
			title := sel.Find("span.normal-title").Text()
			return strings.Contains(title, fieldName)
		})

		if fieldItem.Length() > 0 {
			text := fieldItem.Find("span.normal-text").Text()
			return strings.TrimSpace(text)
		}
	}
	return ""
}

// 重置代理失败计数器（成功时调用）
func resetProxyFailCount() {
	tailProxyMu.Lock()
	defer tailProxyMu.Unlock()
	proxyFailCount = 0
}

// 验证日期格式
func validateDateFormat(dateStr string) int64 {
	// 去除前后空格
	dateStr = strings.TrimSpace(dateStr)

	// 替换各种分隔符为统一的分隔符"-"
	dateStr = regexp.MustCompile(`[/_\\.,\s]+`).ReplaceAllString(dateStr, "-")

	// 处理纯年份格式 (4位数字)
	if regexp.MustCompile(`^\d{4}$`).MatchString(dateStr) {
		dateStr += "-01-01"
	}

	// 处理年月格式 (4位数字-1或2位数字)
	if matches := regexp.MustCompile(`^(\d{4})-(\d{1,2})$`).FindStringSubmatch(dateStr); len(matches) == 3 {
		year := matches[1]
		month := matches[2]
		if len(month) == 1 {
			month = "0" + month
		}
		if monthNum, _ := strconv.Atoi(month); monthNum >= 1 && monthNum <= 12 {
			dateStr = year + "-" + month + "-01"
		} else {
			return 0
		}
	}

	// 处理年月日格式 (4位数字-1或2位数字-1或2位数字)
	if matches := regexp.MustCompile(`^(\d{4})-(\d{1,2})-(\d{1,2})`).FindStringSubmatch(dateStr); len(matches) >= 4 {
		year := matches[1]
		month := matches[2]
		day := matches[3]

		// 标准化月份和日期为两位数
		if len(month) == 1 {
			month = "0" + month
		}
		if len(day) == 1 {
			day = "0" + day
		}

		dateStr = year + "-" + month + "-" + day
	}

	// 加载上海时区
	loc, err := time.LoadLocation("Asia/Shanghai")
	if err != nil {
		// 如果加载时区失败，使用UTC+8作为后备方案
		loc = time.FixedZone("CST", 8*60*60)
	}

	// 尝试解析为标准日期格式，并指定上海时区
	parsedTime, err := time.ParseInLocation("2006-01-02", dateStr, loc)
	if err != nil {
		return 0
	}

	// 返回秒级时间戳（UTC时间，但解析时已经考虑了时区偏移）
	return parsedTime.Unix()
}

// 代理请求(小象代理)
func XxProxyRequest(proxyType, username, password, machineCode string) *gorequest.SuperAgent {
	proxyManagerOnce.Do(func() {
		log.Printf("[INFO] 初始化代理管理器，DLL路径: %s", cf.Proxy.ProxyFilePath)

		// 检查DLL文件是否存在
		if _, err := os.Stat(cf.Proxy.ProxyFilePath); os.IsNotExist(err) {
			// 尝试在可执行文件目录查找
			exePath, _ := os.Executable()
			exeDir := filepath.Dir(exePath)
			dllPath := filepath.Join(exeDir, cf.Proxy.ProxyFilePath)

			if _, err := os.Stat(dllPath); err == nil {
				cf.Proxy.ProxyFilePath = dllPath
			} else {
				proxyManagerInitErr = fmt.Errorf("代理DLL文件不存在: %s (也尝试了: %s)", cf.Proxy.ProxyFilePath, dllPath)
				return
			}
		}

		globalProxyManager, proxyManagerInitErr = NewProxyConfigManager(cf.Proxy.ProxyFilePath)
		if proxyManagerInitErr != nil {
			log.Printf("[ERROR] 代理管理器初始化失败: %v", proxyManagerInitErr)
		} else {
			log.Printf("[INFO] 代理管理器初始化成功")
		}
	})
	typeManager, err := globalProxyManager.ProxyTypeManager(
		proxyType,
		username,
		password,
		machineCode,
	)
	if err != nil {
		fmt.Printf("获取代理服务器信息失败: %v", err)
	}
	return gorequest.New().Proxy(typeManager).Timeout(120*time.Second).Retry(2, 3*time.Second)
}

// 初始化
func initializeConfig(config Config) {
	// 设置全局配置
	cf = config
}

// 连接数据库(选品)
func connectDBXP() (*sql.DB, error) {
	db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
		cf.Database.Username, cf.Database.Password, cf.Database.Host, cf.Database.Name))
	if err != nil {
		return nil, fmt.Errorf("打开数据库连接失败: %v", err)
	}
	// 设置连接池参数
	db.SetMaxOpenConns(20) // 最大打开连接数
	db.SetMaxIdleConns(10) // 最大空闲连接数
	err = db.Ping()
	if err != nil {
		return nil, fmt.Errorf("数据库连接测试失败: %v", err)
	}
	return db, nil
}

// 从数据库随机获取一个可用账号
func getRandomAccount() (*AccountCredential, error) {
	mu.RLock()
	defer mu.RUnlock()
	// sql语句
	query := `
		SELECT id, credential_account, credential_password, token
		FROM t_credential
		WHERE credential_type = 'KWCredential'
		AND status = 0
		AND is_del = 0
		ORDER BY RAND()
		LIMIT 1`

	db, err := connectDBXP()
	if err != nil {
		return nil, err
	}
	var ac AccountCredential
	err = db.QueryRow(query).Scan(&ac.ID, &ac.Username, &ac.Password, &ac.Token)
	if err != nil {
		if err == sql.ErrNoRows {
			return nil, fmt.Errorf("没有可用的账号")
		}
		return nil, fmt.Errorf("查询账号失败: %v", err)
	}
	return &ac, nil
}

// 修改账号为不可用
func updateAccountInvalid(id int64) error {
	mu.RLock()
	defer mu.RUnlock()
	db, err := connectDBXP()
	if err != nil {
		return err
	}
	query := `UPDATE t_credential SET is_del = 1 WHERE id = ?`
	_, err = db.Exec(query, id)
	return fmt.Errorf("更新失败: %v", err)
}

// 修改账号为需要验证
func updateAccountNeedVerify(id int64) error {
	mu.RLock()
	defer mu.RUnlock()
	db, err := connectDBXP()
	if err != nil {
		return err
	}
	query := `UPDATE t_credential SET status = 1 WHERE id = ?`
	_, err = db.Exec(query, id)
	return err
}

// 更新账号token
func updateAccountToken(id int64, token string) error {
	mu.RLock()
	defer mu.RUnlock()
	db, err := connectDBXP()
	if err != nil {
		return err
	}
	query := `UPDATE t_credential SET token = ? WHERE id = ?`
	_, err = db.Exec(query, token, id)
	return err
}

// 登录(带有Out的都非官方标准接口)
//
//export OutLogin
func OutLogin(username, password *C.char) *C.char {
	goUsername := C.GoString(username)
	goPassword := C.GoString(password)
	respToken, err := outLogin(goUsername, goPassword)
	resp := struct {
		Token string `json:"token"`
	}{
		Token: respToken,
	}
	var apiResponse APIResponse
	if err != nil {
		apiResponse = APIResponse{
			Success: false,
			Message: err.Error(),
		}
	} else {
		apiResponse = APIResponse{
			Success: true,
			Data:    resp,
		}
	}
	// 转换为JSON字符串
	jsonData, marshalErr := json.Marshal(apiResponse)
	if marshalErr != nil {
		// 如果JSON序列化失败，返回错误信息
		apiResponse = APIResponse{
			Success: false,
			Message: fmt.Sprintf("JSON序列化失败: %v", marshalErr),
		}
		errorJson, _ := json.Marshal(apiResponse)
		return C.CString(string(errorJson))
	}
	return C.CString(string(jsonData))
}

// 获取用户信息(带有Out的都非官方标准接口)
//
//export OutGetUserMsg
func OutGetUserMsg(token *C.char) *C.char {
	goToken := C.GoString(token)
	userInfo, err := outGetUserMsg(goToken)
	var apiResponse APIResponse
	if err != nil {
		apiResponse = APIResponse{
			Success: false,
			Message: err.Error(),
		}
	} else {
		apiResponse = APIResponse{
			Success: true,
			Data:    userInfo,
		}
	}
	// 转换为JSON字符串
	jsonData, marshalErr := json.Marshal(apiResponse)
	if marshalErr != nil {
		// 如果JSON序列化失败，返回错误信息
		apiResponse = APIResponse{
			Success: false,
			Message: fmt.Sprintf("JSON序列化失败: %v", marshalErr),
		}
		errorJson, _ := json.Marshal(apiResponse)
		return C.CString(string(errorJson))
	}
	return C.CString(string(jsonData))
}

// 获取商品模版(带有Out的都非官方标准接口)
//
//export OutGetGoodsTplMsg
func OutGetGoodsTplMsg(token, itemId, proxy *C.char) *C.char {
	goToken := C.GoString(token)
	goItemId := C.GoString(itemId)
	goProxy := C.GoString(proxy)
	info, err := outGetGoodsTplMsg(goToken, goItemId, goProxy)
	var apiResponse APIResponse
	if err != nil {
		apiResponse = APIResponse{
			Success: false,
			Message: err.Error(),
		}
	} else {
		apiResponse = APIResponse{
			Success: true,
			Data:    info,
		}
	}
	// 转换为JSON字符串
	jsonData, marshalErr := json.Marshal(apiResponse)
	if marshalErr != nil {
		// 如果JSON序列化失败，返回错误信息
		apiResponse = APIResponse{
			Success: false,
			Message: fmt.Sprintf("JSON序列化失败: %v", marshalErr),
		}
		errorJson, _ := json.Marshal(apiResponse)
		return C.CString(string(errorJson))
	}
	return C.CString(string(jsonData))
}

// 获取商品列表-已登的店铺(带有Out的都非官方标准接口)
//
//export OutGetGoodsListMsgFromSelfShop
func OutGetGoodsListMsgFromSelfShop(token, proxy, itemSn, priceMin, priceMax *C.char, startCreateTime C.int,
	endCreateTime C.int, requestType *C.char, isItemSnEqual C.int, page C.int, size C.int) *C.char {
	goToken := C.GoString(token)
	goProxy := C.GoString(proxy)
	goItemSn := C.GoString(itemSn)
	goPriceMin := C.GoString(priceMin)
	goPriceMax := C.GoString(priceMax)
	goStartCreateTime := int(startCreateTime)
	goEndCreateTime := int(endCreateTime)
	goRequestType := C.GoString(requestType)
	goIsItemSnEqual := int(isItemSnEqual)
	goPage := int(page)
	goSize := int(size)
	info, err := outGetGoodsListMsgFromSelfShop(goToken, goProxy, goItemSn, goPriceMin, goPriceMax, goStartCreateTime, goEndCreateTime, goRequestType, goIsItemSnEqual, goPage, goSize)
	var apiResponse APIResponse
	if err != nil {
		apiResponse = APIResponse{
			Success: false,
			Message: err.Error(),
		}
	} else {
		apiResponse = APIResponse{
			Success: true,
			Data:    info,
		}
	}
	// 转换为JSON字符串
	jsonData, marshalErr := json.Marshal(apiResponse)
	if marshalErr != nil {
		// 如果JSON序列化失败，返回错误信息
		apiResponse = APIResponse{
			Success: false,
			Message: fmt.Sprintf("JSON序列化失败: %v", marshalErr),
		}
		errorJson, _ := json.Marshal(apiResponse)
		return C.CString(string(errorJson))
	}
	return C.CString(string(jsonData))
}

// 新增商品(带有Out的都非官方标准接口)
//
//export OutAddGoods
func OutAddGoods(token, proxy, formData *C.char) *C.char {
	goToken := C.GoString(token)
	goProxy := C.GoString(proxy)
	goFormData := C.GoString(formData)
	info, err := outAddGoods(goToken, goProxy, goFormData)
	var apiResponse APIResponse
	if err != nil {
		apiResponse = APIResponse{
			Success: false,
			Message: err.Error(),
		}
	} else {
		apiResponse = APIResponse{
			Success: true,
			Data:    info,
		}
	}
	// 转换为JSON字符串
	jsonData, marshalErr := json.Marshal(apiResponse)
	if marshalErr != nil {
		// 如果JSON序列化失败，返回错误信息
		apiResponse = APIResponse{
			Success: false,
			Message: fmt.Sprintf("JSON序列化失败: %v", marshalErr),
		}
		errorJson, _ := json.Marshal(apiResponse)
		return C.CString(string(errorJson))
	}
	return C.CString(string(jsonData))
}

// 获取商品图片(带有Out的都非官方标准接口)
//
//export OutGetImageByIsbn
func OutGetImageByIsbn(token, isbn, proxy *C.char, isLiveImage C.int, isReturnMsg C.int) *C.char {
	goToken := C.GoString(token)
	goIsbn := C.GoString(isbn)
	goProxy := C.GoString(proxy)
	goIsLiveImage := int(isLiveImage)
	goIsReturnMsg := int(isReturnMsg)
	bookInfo, err := outGetImageByIsbn(goToken, goIsbn, goProxy, goIsLiveImage, goIsReturnMsg)
	var apiResponse APIResponse
	if err != nil {
		apiResponse = APIResponse{
			Success: false,
			Message: err.Error(),
		}
	} else {
		apiResponse = APIResponse{
			Success: true,
			Data:    bookInfo,
		}
	}
	// 转换为JSON字符串
	jsonData, marshalErr := json.Marshal(apiResponse)
	if marshalErr != nil {
		// 如果JSON序列化失败，返回错误信息
		apiResponse = APIResponse{
			Success: false,
			Message: fmt.Sprintf("JSON序列化失败: %v", marshalErr),
		}
		errorJson, _ := json.Marshal(apiResponse)
		return C.CString(string(errorJson))
	}
	return C.CString(string(jsonData))
}

// 获取商品列表通过店铺ID(带有Out的都非官方标准接口)
//
//export OutGetGoodsListMsgByShopId
func OutGetGoodsListMsgByShopId(shopId C.int, proxy *C.char, isImage C.int, sortType *C.char, sort *C.char, priceMin C.float, priceMax C.float, pageNum, returnNum C.int) *C.char {
	goShopId := int(shopId)
	goProxy := C.GoString(proxy)
	goIsImage := int(isImage)
	goSortType := C.GoString(sortType)
	goSort := C.GoString(sort)
	goPriceMin := float32(priceMin)
	goPriceMax := float32(priceMax)
	goPageNum := int(pageNum)
	goReturnNum := int(returnNum)
	books, num, pNum, err := outGetGoodsListMsgByShopId(goShopId, goProxy, goIsImage, goSortType, goSort, goPriceMin, goPriceMax, goPageNum, goReturnNum)
	// 构建统一格式的响应
	bookInfo := struct {
		GoodsNum string      `json:"goods_num,omitempty"`
		PNum     string      `json:"pnum,omitempty"`
		Data     interface{} `json:"data,omitempty"`
	}{
		GoodsNum: num,
		PNum:     pNum,
		Data:     books,
	}
	var apiResponse APIResponse
	if err != nil {
		apiResponse = APIResponse{
			Success: false,
			Message: err.Error(),
		}
	} else {
		apiResponse = APIResponse{
			Success: true,
			Data:    bookInfo,
		}
	}
	// 转换为JSON字符串
	jsonData, marshalErr := json.Marshal(apiResponse)
	if marshalErr != nil {
		// 如果JSON序列化失败，返回错误信息
		apiResponse = APIResponse{
			Success: false,
			Message: fmt.Sprintf("JSON序列化失败: %v", marshalErr),
		}
		errorJson, _ := json.Marshal(apiResponse)
		return C.CString(string(errorJson))
	}
	return C.CString(string(jsonData))
}

// 获取商品信息通过商品详情链接(带有0ut的都非官方标准接口)
//
//export OutGetGoodsMsgByDetailUrl
func OutGetGoodsMsgByDetailUrl(detailUrl, proxy *C.char) *C.char {
	goDetailUrl := C.GoString(detailUrl)
	goProxy := C.GoString(proxy)
	response, err := outGetGoodsMsgByDetailUrl(goDetailUrl, goProxy)
	// 构建统一格式的响应
	var apiResponse APIResponse
	if err != nil {
		apiResponse = APIResponse{
			Success: false,
			Message: err.Error(),
		}
	} else {
		apiResponse = APIResponse{
			Success: true,
			Data:    response,
		}
	}
	// 转换为JSON字符串
	jsonData, marshalErr := json.Marshal(apiResponse)
	if marshalErr != nil {
		// 如果JSON序列化失败，返回错误信息
		apiResponse = APIResponse{
			Success: false,
			Message: fmt.Sprintf("JSON序列化失败: %v", marshalErr),
		}
		errorJson, _ := json.Marshal(apiResponse)
		return C.CString(string(errorJson))
	}
	return C.CString(string(jsonData))
}

// 获取销量榜商品列表(带有Out的都非官放标准接口)
//
//export OutGetTopGoodsListMsg
func OutGetTopGoodsListMsg(catId C.int, proxy *C.char) *C.char {
	goCatId := int(catId)
	goProxy := C.GoString(proxy)
	response, err := outGetTopGoodsListMsg(goCatId, goProxy)
	// 构建统一格式的响应
	var apiResponse APIResponse
	if err != nil {
		apiResponse = APIResponse{
			Success: false,
			Message: err.Error(),
		}
	} else {
		apiResponse = APIResponse{
			Success: true,
			Data:    response,
		}
	}
	// 转换为JSON字符串
	jsonData, marshalErr := json.Marshal(apiResponse)
	if marshalErr != nil {
		// 如果JSON序列化失败，返回错误信息
		apiResponse = APIResponse{
			Success: false,
			Message: fmt.Sprintf("JSON序列化失败: %v", marshalErr),
		}
		errorJson, _ := json.Marshal(apiResponse)
		return C.CString(string(errorJson))
	}
	return C.CString(string(jsonData))
}

//export Initialize
func Initialize(configJSON *C.char) *C.char {
	configStr := C.GoString(configJSON)
	log.Printf("[DEBUG] 接收到的配置JSON: %s", configStr)

	var config Config
	if err := json.Unmarshal([]byte(configStr), &config); err != nil {
		return C.CString(fmt.Sprintf(`{"success":false,"message":"配置解析失败: %v"}`, err))
	}
	initializeConfig(config)

	return C.CString(`{"success":true,"message":"初始化成功"}`)
}

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

//// 空main函数，编译DLL时需要
//func main() {
//
//}
