package service

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"strconv"
	"strings"
	"sync"
	"time"

	"kfz-goods-pricing/internal/model"
	"kfz-goods-pricing/internal/repository"

	"github.com/parnurzeal/gorequest"
)

// GoodsService 商品服务
type GoodsService struct {
	proxy               string
	apiRateLimitSeconds int
	rateLimitMu         sync.Mutex
	lastAPICall         time.Time
	goodsRepository     *repository.GoodsRepository
	callbackURL         string
	tokenRepository     *repository.TokenRepository
	currentTokenIndex   int
	tokenMu             sync.Mutex
}

// NewGoodsService 创建商品服务实例
func NewGoodsService(proxy string, apiRateLimitSeconds int, callbackURL string, tokenRepo *repository.TokenRepository) *GoodsService {
	return &GoodsService{
		proxy:               proxy,
		apiRateLimitSeconds: apiRateLimitSeconds,
		goodsRepository:     repository.NewGoodsRepository(),
		callbackURL:         callbackURL,
		tokenRepository:     tokenRepo,
		currentTokenIndex:   0,
	}
}

// QueryRequest 查询请求参数 {"isbn":"9787802204461","out_id":"132456","quality":"100"}
type QueryRequest struct {
	ISBN                 string  `json:"isbn"`                   // isbn
	BookName             string  `json:"book_name"`              // 书名
	Author               string  `json:"author"`                 // 作者
	Publishing           string  `json:"publishing"`             // 出版社
	OutID                string  `json:"out_id"`                 // 输出ID
	Quality              string  `json:"quality"`                // 品相
	QueryIndex           int     `json:"query_index"`            // 排第几位
	UserID               string  `json:"user_id"`                // 用户ID
	PlaceholderDownPrice float64 `json:"placeholder_down_price"` // 占位降价
	MinShippingFee       float64 `json:"min_shipping_fee"`       // 最低运费
	MinPrice             float64 `json:"min_price"`              // 最低书价
}

// QueryResponse 查询响应
type QueryResponse struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
	ID      int64       `json:"id,omitempty"`
	Data    interface{} `json:"data,omitempty"`
}

// QueryGoods 查询商品信息
func (s *GoodsService) QueryGoods(req *QueryRequest) *QueryResponse {
	if req.ISBN == "0" {
		return &QueryResponse{
			Code:    200,
			Message: "success",
		}
	}

	// 插入入参记录到数据库
	id, err := s.goodsRepository.Insert(req.ISBN, req.BookName, req.Author, req.Publishing, req.OutID, req.Quality, req.UserID, req.QueryIndex, req.PlaceholderDownPrice, req.MinShippingFee, req.MinPrice)
	if err != nil {
		return &QueryResponse{
			Code:    500,
			Message: fmt.Sprintf("保存记录失败: %v", err),
		}
	}

	return &QueryResponse{
		Code:    200,
		Message: "success",
		ID:      id,
	}
}

// rateLimitWait 限流等待
func (s *GoodsService) rateLimitWait() {
	if s.apiRateLimitSeconds <= 0 {
		return
	}

	s.rateLimitMu.Lock()
	defer s.rateLimitMu.Unlock()

	elapsed := time.Since(s.lastAPICall)
	if elapsed < time.Duration(s.apiRateLimitSeconds)*time.Second {
		time.Sleep(time.Duration(s.apiRateLimitSeconds)*time.Second - elapsed)
	}
	s.lastAPICall = time.Now()
}

// sendCallback 发送回调请求
func (s *GoodsService) sendCallback(outID, userID string, price, shippingFee float64) {
	if s.callbackURL == "" {
		return
	}

	// price*100 转int, shipping_fee*100 转int
	salePrice := int(price * 100)
	cost := int(shippingFee * 100)

	request := gorequest.New()
	if s.proxy != "" {
		request.Proxy(s.proxy)
	}
	_, _, errs := request.Post(s.callbackURL).
		Set("Content-Type", "application/x-www-form-urlencoded").
		Send(fmt.Sprintf("product_id=%s&user_id=%s&sale_price=%d&cost=%d", outID, userID, salePrice, cost)).
		Timeout(30 * time.Second).
		End()

	if len(errs) > 0 {
		log.Printf("回调失败: %v", errs)
	} else {
		log.Printf("回调成功: product_id=%s, user_id=%s, sale_price=%d, cost=%d", outID, userID, salePrice, cost)
	}
}

// StartTimerScheduler 启动定时器
func (s *GoodsService) StartTimerScheduler(intervalSeconds int) {
	ticker := time.NewTicker(time.Duration(intervalSeconds) * time.Second)
	go func() {
		for range ticker.C {
			s.syncGoodsPricing()
		}
	}()
}

// syncGoodsPricing 定时同步商品价格
func (s *GoodsService) syncGoodsPricing() {
	//cfg := config.GetGlobal()
	// 查询数据库数据
	kfzConfig, err := repository.GetKfzConfig()
	if err != nil {
		log.Printf("获取config数据库数据失败: %v", err)
		return
	}

	// 查询一条记录，按fail_count升序、updated_at倒序
	record, err := s.goodsRepository.GetAllOrderByUpdatedAt()
	if err != nil {
		log.Printf("定时任务查询失败: %v", err)
		return
	}
	if record == nil {
		return
	}

	// 限流等待
	s.rateLimitWait()

	var price float64
	var shippingFee float64
	// 最终书价
	var finalPrice float64

	// 查询孔网数据
	bookInfo, err := s.outGetAllGoods(record.ISBN, record.BookName, record.Author, record.Publishing, record.Quality, record.QueryIndex)
	if err != nil {
		if kfzConfig.NewPrice == 0 {
			s.goodsRepository.MarkFailed(record.ID)
			log.Printf("定时任务[%d]查询孔网失败(fail_count=%d): %v", record.ID, record.FailCount+1, err)
			return
		}
		finalPrice = kfzConfig.NewPrice
	} else {
		// 查询成功，更新价格
		price, _ = strconv.ParseFloat(bookInfo.Price, 64)
		shippingFee, _ = strconv.ParseFloat(bookInfo.ShippingFee, 64)
		totalPrice := price + shippingFee
		finalPrice = totalPrice - record.PlaceholderDownPrice - record.MinShippingFee
		if finalPrice < record.MinPrice {
			finalPrice = record.MinPrice
		}
		// 保留两位小数
		finalPrice, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", finalPrice), 64)
	}

	if err := s.goodsRepository.UpdatePrice(record.ID, price, shippingFee, finalPrice); err != nil {
		log.Printf("定时任务[%d]更新价格失败: %v", record.ID, err)
		return
	}

	log.Printf("定时任务[%d]更新成功: price=%.2f, shipping_fee=%.2f", record.ID, price, shippingFee)

	// 调用回调
	s.sendCallback(record.OutID, record.UserID, finalPrice, record.MinShippingFee)
}

// outGetAllGoods 爬取孔网所有商品页面
func (s *GoodsService) outGetAllGoods(isbn string, bookName string, author string, publishing string, quality string, queryIndex int) (*model.BookInfo, error) {
	var actionPathList []string

	// 从数据库获取启用的token列表
	tokens, err := s.tokenRepository.GetEnabledTokens()
	if err != nil || len(tokens) == 0 {
		return nil, fmt.Errorf("没有可用的token")
	}

	// 轮询选择token
	s.tokenMu.Lock()
	s.currentTokenIndex = s.currentTokenIndex % len(tokens)
	currentIdx := s.currentTokenIndex
	s.currentTokenIndex++
	s.tokenMu.Unlock()

	token := tokens[currentIdx].Token

	//kfzUrl := "https://search.kongfz.com/pc-gw/search-web/client/pc/product/keyword/list?dataType=0&page=1&sortType=7&quaSelect=2"
	kfzUrl := "https://search.kongfz.com/pc-gw/search-web/client/pc/product/keyword/list?dataType=0&page=1&sortType=7&userArea=13003000000&quaSelect=2"

	// 整理查询参数-加上排序
	actionPathList = append(actionPathList, "sortType")

	// isbn
	if isbn != "" {
		kfzUrl = kfzUrl + "&keyword=" + isbn
	}

	// 书名
	if bookName != "" {
		kfzUrl = kfzUrl + "&keyword=" + bookName
	}

	// 作者
	if author != "" {
		kfzUrl = kfzUrl + "&author=" + author
	}

	// 出版社
	if publishing != "" {
		kfzUrl = kfzUrl + "&press=" + publishing
	}

	// 品相
	if quality != "" {
		kfzUrl = kfzUrl + "&quality=" + quality + "~"
		actionPathList = append(actionPathList, "quality")
	}

	// 参数进行分割
	actionPath := strings.Join(actionPathList, ",")
	// 加入查询参数
	kfzUrl = kfzUrl + "&actionPath=" + actionPath

	// 创建HTTP客户端
	requestSpt := gorequest.New()

	// 设置代理(如果有提供代理URL)
	if s.proxy != "" {
		requestSpt.Proxy(s.proxy)
	}
	fmt.Println("请求地址：", kfzUrl)
	// 发送请求
	respSpt, bodySpt, errsSpt := requestSpt.Get(kfzUrl).
		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://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)
	}

	fmt.Println("响应数据:", bodySpt)

	// 解析响应
	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 {
					Title       string  `json:"title"`
					Author      string  `json:"author"`
					Press       string  `json:"press"`
					PubDateText string  `json:"pubDateText"`
					Isbn        string  `json:"isbn"`
					Price       float64 `json:"price"`
					Postage     struct {
						ShippingList []struct {
							ShippingFee float64 `json:"shippingFee"`
						} `json:"shippingList"`
					} `json:"postage"`
				} `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.Status != 1 {
		return nil, fmt.Errorf("错误信息: %v，状态码: %s", apiSptResp.Message, apiSptResp.ErrType)
	}

	bookInfo := &model.BookInfo{}

	if apiSptResp.Data.ItemResponse.Total > 0 && len(apiSptResp.Data.ItemResponse.List) > 0 {
		if queryIndex > 0 && queryIndex <= len(apiSptResp.Data.ItemResponse.List) {
			goodsInfo := apiSptResp.Data.ItemResponse.List[queryIndex-1]
			bookInfo.BookName = goodsInfo.Title
			bookInfo.ISBN = goodsInfo.Isbn
			bookInfo.Author = goodsInfo.Author
			bookInfo.Publisher = goodsInfo.Press
			bookInfo.PubDate = goodsInfo.PubDateText
			bookInfo.Price = fmt.Sprintf("%.2f", goodsInfo.Price)
			for _, shipping := range goodsInfo.Postage.ShippingList {
				bookInfo.ShippingFee = fmt.Sprintf("%.2f", shipping.ShippingFee)
			}
		} else {
			goodsInfo := apiSptResp.Data.ItemResponse.List[len(apiSptResp.Data.ItemResponse.List)-1]
			bookInfo.BookName = goodsInfo.Title
			bookInfo.ISBN = goodsInfo.Isbn
			bookInfo.Author = goodsInfo.Author
			bookInfo.Publisher = goodsInfo.Press
			bookInfo.PubDate = goodsInfo.PubDateText
			bookInfo.Price = fmt.Sprintf("%.2f", goodsInfo.Price)
			for _, shipping := range goodsInfo.Postage.ShippingList {
				bookInfo.ShippingFee = fmt.Sprintf("%.2f", shipping.ShippingFee)
			}
		}
		return bookInfo, nil
	}

	return nil, fmt.Errorf("查询失败，没有数据！")
}
