package services

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"go-account-register/libs"
	"go-account-register/models"
	"go-account-register/utils"
	"log"
	"math/rand"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/go-rod/rod"
	"github.com/go-rod/rod/lib/cdp"
	"github.com/go-rod/rod/lib/input"
	"github.com/go-rod/rod/lib/proto"
)

type TwitterService struct{}

// 登录
func (*TwitterService) Login(id int) *libs.ErrorInfo {
	UserService := InitTwitterAccountService()
	user := UserService.GetInfo(int64(id))
	obj := Browser.GetBrowser(id, &libs.Fingerprint{
		Proxy: user.Proxy,
	})
	browser := obj.Browser
	page := obj.Page

	err3 := rod.Try(func() {
		// 创建 Cookie 对象
		// cookies := user.Cookies
		// log.Println("获取cookie", cookies)
		// b, _ := json.MarshalIndent(cookies, "", "  ")
		// log.Println(string(b))

		// var token string
		// for _, v := range user.Cookies {
		// 	if v.Name == "auth_token" {
		// 		token = v.Value
		// 	}
		// }
		// log.Println("当前账号Token", token)
		cookies := []*proto.NetworkCookieParam{
			{
				Name:     "auth_token",
				Value:    user.Token,
				Domain:   ".x.com",
				Path:     "/",
				Expires:  proto.TimeSinceEpoch(time.Now().Add(24 * time.Hour).Unix()), // 过期时间
				HTTPOnly: true,                                                        // 禁止 JS 访问
				Secure:   true,                                                        // 仅 HTTPS 传输
			},
		}
		log.Println("Cookie", cookies[0].Value)
		// 全局设置
		browser.SetCookies(cookies)
		page.MustNavigate("https://x.com/home").MustWaitLoad()
		page.MustWaitNavigation()
	})
	if e, ok := err3.(*cdp.Error); ok {
		if e.Code == -32000 && e.Message == "Inspected target navigated or closed" {
			Browser.CancelBrowser(id)
			return libs.ErrorCode["LoginFailed"]
		}
	}

	time.Sleep(3 * time.Second)
	url := page.MustEval("() => window.location.href").String()
	if url == "https://x.com/account/access" {
		Browser.CancelBrowser(id)
		return libs.ErrorCode["AccountLocked"]
	}
	log.Println(url)
	err1 := rod.Try(func() {
		page.Timeout(5 * time.Second).MustElement(`input[autocomplete="username"]`)
	})
	if err1 == nil {
		Browser.CancelBrowser(id)
		return libs.ErrorCode["LoginFailed"]
	}
	// 是否检测到侧边栏
	err2 := rod.Try(func() {
		page.Timeout(5 * time.Second).MustElement(`a[data-testid="AppTabBar_Profile_Link"]`)
	})

	if err2 != nil {
		Browser.CancelBrowser(id)
		return libs.ErrorCode["LoginFailed"]
	}

	// 是否检测到帖子列表
	err := rod.Try(func() {
		page.Timeout(5 * time.Second).MustElement(`article[data-testid="tweet"]`)
	})

	if errors.Is(err, context.DeadlineExceeded) {
		fmt.Println("请求空闲等待超时！")
		// 关闭浏览器
		Browser.CancelBrowser(id)
		return libs.ErrorCode["NetworkTimeout"]
	}
	if err != nil {
		fmt.Println(err)
	}
	getAccountInfo(page, int64(id))
	return libs.ErrorCode["LoginSuccessful"]
}

// 获取账号信息
func getAccountInfo(page *rod.Page, id int64) {
	profileButton := page.Timeout(10 * time.Second).MustElement(`a[data-testid="AppTabBar_Profile_Link"]`)
	profileButton.MustClick()
	// 等待新页面加载完成
	page.MustWaitLoad()
	res := getApiResponse(page, "/UserByScreenName")
	var dataBody map[string]interface{}
	json.Unmarshal([]byte(res), &dataBody)
	outerMap := dataBody["data"].(map[string]interface{})
	userMap := outerMap["user"].(map[string]interface{})
	resultMap := userMap["result"].(map[string]interface{})

	// 获取头像
	avatarMap := resultMap["avatar"].(map[string]interface{})
	avatarImageURL := avatarMap["image_url"].(string)
	legacyMap := resultMap["legacy"].(map[string]interface{})
	// 获取背景图
	backdropImgUrl := legacyMap["profile_banner_url"]
	var backdropUrl string
	if backdropImgUrl == nil {
		backdropUrl = ""
	} else {
		backdropUrl = legacyMap["profile_banner_url"].(string)
	}

	// 获取昵称
	coreMap := resultMap["core"].(map[string]interface{})
	nickname := coreMap["name"].(string)
	screenName := coreMap["screen_name"].(string)
	// 获取自我介绍
	bio := legacyMap["description"].(string)

	// 获取自己设置的地理位置
	locationObj := resultMap["location"].(map[string]interface{})
	location := locationObj["location"].(string)
	// 获取粉丝数量
	followersCount := legacyMap["followers_count"].(float64)
	// 获取关注数量
	friendsCount := legacyMap["friends_count"].(float64)
	// 获取发布的帖子数量
	mediaCount := legacyMap["media_count"].(float64)
	log.Println("头像地址", avatarImageURL)
	log.Println("背景图地址", backdropUrl)
	log.Println("昵称", nickname)
	log.Println("用户名", screenName)
	log.Println("自我介绍", bio)
	log.Println("地理位置", location)
	log.Println("粉丝数量", int64(followersCount))
	log.Println("关注数量", int64(friendsCount))
	log.Println("发布的帖子数量", int64(mediaCount))
	userService := InitTwitterAccountService()
	userService.Update(id, &models.TwitterAccount{
		Uid: screenName,
	})
}

// 退出登录
func (*TwitterService) Logout(id int) {
	Browser.CancelBrowser(id)
}

// 注册账号
func (bit *TwitterService) Register() *libs.ErrorInfo {
	// 随机获取代理
	proxyService := InitProxyService()
	proxy := proxyService.GetInfo()

	// 获取一个邮箱
	emailService := InitEmailService()

	emailInfo := emailService.GetEmailOne()
	log.Println("当前邮箱信息", emailInfo)
	obj := Browser.GetNewBrowser(&libs.Fingerprint{})
	page := obj.Page
	page.MustNavigate("https://x.com/").MustWaitLoad()
	// 点击创建账号
	createAccountA := page.Timeout(5 * time.Second).MustElement(`a[data-testid="signupButton"]`)
	createAccountA.MustClick()

	// // 点击创建账号
	// createAccount := page.Timeout(5 * time.Second).MustElement(`button.css-175oi2r.r-sdzlij.r-1phboty.r-rs99b7.r-lrvibr.r-ywje51.r-184id4b.r-13qz1uu.r-2yi16.r-1qi8awa.r-3pj75a.r-1loqt21.r-o7ynqc.r-6416eg.r-1ny4l3l`)
	// createAccount.MustClick()
	// 判断当前是否是邮箱注册
	// _, err := page.Element(`input[name="email"]`)
	// if err != nil {
	switchButton := page.Timeout(5 * time.Second).MustElement(`button.css-146c3p1.r-bcqeeo.r-qvutc0.r-37j5jr.r-1ff274t.r-a023e6.r-rjixqe.r-16dba41`)
	switchButton.MustClick()
	// }
	// 获取邮箱输入框
	inputEmail := page.Timeout(5 * time.Second).MustElement(`input[name="email"]`)
	inputEmail.MustFocus()
	inputEmail.MustInput(emailInfo.Email)
	// 获取名称输入框
	inputName := page.Timeout(5 * time.Second).MustElement(`input[name="name"]`)
	inputName.MustFocus()
	nameStr := emailInfo.Name
	if emailInfo.Name == "" {
		nameStr = utils.RandString(12)
	}
	inputName.MustInput(nameStr)
	// 随机生成生日
	dateParams := utils.RandDate(18, 80)
	dateSelects, _ := page.Timeout(5 * time.Second).Elements(`select.r-30o5oe.r-1niwhzg.r-17gur6a.r-1yadl64.r-18jsvk2.r-1loqt21.r-1inkyih.r-rjixqe.r-crgep1.r-1wzrnnt.r-1ny4l3l.r-t60dpp.r-xd6kpl.r-is05cd.r-ttdzmv`)
	log.Println(dateSelects)
	fmt.Println(strconv.Itoa(dateParams.Month))
	fmt.Println(strconv.Itoa(dateParams.Day))
	fmt.Println(strconv.Itoa(dateParams.Year))
	time.Sleep(2 * time.Second)
	// 月份
	dateSelects[0].WaitVisible()
	opts, _ := dateSelects[0].Elements("option")
	for i, opt := range opts {
		txt, _ := opt.Text()
		val, _ := opt.Attribute("value")
		log.Printf("option[%d] text=%s value=%s\n", i, txt, *val)
		if i != 0 && i == dateParams.Month {
			dateSelects[0].MustSelect(txt)
		}
	}
	// 年份
	dateSelects[2].WaitVisible()
	dateSelects[2].MustSelect(strconv.Itoa(dateParams.Year))
	time.Sleep(2 * time.Second)
	// 日期
	dateSelects[1].WaitVisible()
	dateSelects[1].MustSelect(strconv.Itoa(dateParams.Day))
	// dateSelects[0].MustClick()
	// monthOption := dateSelects[0].MustElement(fmt.Sprintf(`option[value="%d"]`, dateParams.Month))
	// monthOption.MustClick()
	time.Sleep(2 * time.Second)
	// 点击下一步
	ocfSignupNextLink := page.Timeout(5 * time.Second).MustElement(`button[data-testid="ocfSignupNextLink"]`)
	ocfSignupNextLink.MustClick()
	// 判断是否需要验证码
	time.Sleep(4 * time.Second)
	_, err1 := page.Timeout(5 * time.Second).Element(`input[name="verfication_code"]`)
	if err1 != nil {
		// res := getApiResponse(page, "")
	}
	//TODO 对接获取邮箱信息接口
	time.Sleep(10 * time.Second)
	codeValue := LoopGetEmailCode("pop.dragonsmail.com:993", emailInfo.Email, emailInfo.Password)
	if codeValue == "0" {
		emailService.Update(emailInfo.Email, models.Email{
			Status: 0,
		})
		return libs.ErrorCode["MailboxUnavailable"]
	}
	// 获取邮箱验证码
	log.Println("获取当前验证码", codeValue)
	codeInput1, _ := page.Timeout(5 * time.Second).Element(`input[name="verfication_code"]`)
	codeInput1.MustInput(codeValue)
	time.Sleep(2 * time.Second)
	// 点击下一步
	codeNextButton := page.Timeout(5 * time.Second).MustElement(`button.css-175oi2r.r-sdzlij.r-1phboty.r-rs99b7.r-lrvibr.r-19yznuf.r-64el8z.r-1fkl15p.r-1loqt21.r-o7ynqc.r-6416eg.r-1ny4l3l`)
	codeNextButton.MustClick()
	// // 点击验证按钮
	// verifyButton := page.Timeout(5 * time.Second).MustElement(`button[data-theme="home.verifyButton"]`)
	// verifyButton.MustClick()
	// 输入密码
	passwordInput, err2 := page.Timeout(5 * time.Second).Element(`input[name="password"]`)
	if err2 != nil {
		// res := getApiResponse(page, "")
	}

	passwordInput.MustInput(emailInfo.Password)
	time.Sleep(5 * time.Second)
	// 点击下一步
	loginButton := page.Timeout(5 * time.Second).MustElement(`button[data-testid="LoginForm_Login_Button"]`)
	loginButton.MustClick()
	time.Sleep(5 * time.Second)
	page.MustNavigate("https://x.com").MustWaitLoad()
	time.Sleep(10 * time.Second)
	// 获取cookie
	cookieArr := GetPageCookie(page, "https://x.com")
	// 创建用户
	twitterAccountService := InitTwitterAccountService()
	twitterAccountService.Create(&models.TwitterAccount{
		Name:        nameStr,
		Email:       emailInfo.Email,
		Password:    emailInfo.Password,
		Birthday:    strconv.Itoa(dateParams.Year) + "-" + strconv.Itoa(dateParams.Month) + "-" + strconv.Itoa(dateParams.Day),
		Cookies:     cookieArr,
		Status:      "注册成功",
		LoginStatus: "登录成功",
		Proxy: func() string {
			if proxy != nil && proxy.Type != "" {
				return proxy.Type + "://" + proxy.Proxy
			}
			return ""
		}(),
	})
	emailService.Update(emailInfo.Email, models.Email{
		UseStatus: 1,
	})
	// 设置fa2
	page.MustNavigate("https://x.com/settings/account/login_verification").MustWaitLoad()
	// 点击fa2按钮
	inputCheckbox := page.Timeout(5 * time.Second).MustElement(`input[aria-describedby="CHECKBOX_2_LABEL"]`)
	inputCheckbox.MustClick()
	// 等待2秒
	time.Sleep(2 * time.Second)
	// 设置密码
	inpurPassword := page.Timeout(5 * time.Second).MustElement(`input[name="password"]`)
	inpurPassword.MustInput(emailInfo.Password)
	// 点击确认
	faConfirm := page.Timeout(5 * time.Second).MustElement(`button[data-testid="LoginForm_Login_Button"]`)
	faConfirm.MustClick()
	// 等待2秒
	time.Sleep(2 * time.Second)
	ActionListNextButton := page.Timeout(5 * time.Second).MustElement(`button[data-testid="ActionListNextButton"]`)
	ActionListNextButton.MustClick()
	// 点击无法扫描二维码
	queryCode := page.Timeout(5 * time.Second).MustElement("div.css-175oi2r.r-1awozwy.r-w7s2jr>div.css-175oi2r.r-95jzfe>div.css-146c3p1.r-bcqeeo.r-1ttztb7.r-qvutc0.r-37j5jr.r-a023e6.r-rjixqe.r-16dba41>button.css-1jxf684.r-bcqeeo.r-qvutc0.r-poiln3.r-fdjqy7")
	queryCode.MustClick()
	fa2Code := page.Timeout(5 * time.Second).MustElement(`div.css-146c3p1.r-bcqeeo.r-qvutc0.r-37j5jr.r-1blvdjr.r-vrz42v.r-b88u0q.r-x572qd.r-ywje51.r-1oqcu8e.r-q4m81j.r-13qz1uu`)
	fa2CodeText := fa2Code.MustText()
	log.Println("当前账号的二步验证码，", fa2CodeText)
	ocfShowCodeNextLink := page.Timeout(5 * time.Second).MustElement(`button[data-testid="ocfShowCodeNextLink"]`)
	ocfShowCodeNextLink.MustClick()
	codeText, _ := utils.GetFA2Code(fa2CodeText)
	ocfEnterTextTextInput := page.Timeout(5 * time.Second).MustElement(`input[data-testid="ocfEnterTextTextInput"]`)
	ocfEnterTextTextInput.MustInput(codeText)
	ocfEnterTextNextButton := page.Timeout(5 * time.Second).MustElement(`button[data-testid="ocfEnterTextNextButton"]`)
	ocfEnterTextNextButton.MustClick()
	// 删除浏览器
	return libs.ErrorCode["RegisterSuccessful"]

}

// 发推
func (*TwitterService) SendPost(accountId int, Content string, Img []string) *libs.ErrorInfo {
	// 获取账号状态
	UserService := InitTwitterAccountService()
	user := UserService.GetInfo(int64(accountId))
	if user.LoginStatus != "登录成功" {
		return libs.ErrorCode["AccountHasBeenTakenOffline"]
	}
	// 获取实例
	obj := Browser.GetBrowser(accountId, &libs.Fingerprint{
		Proxy: user.Proxy,
	})
	page := obj.Page
	// 跳转到首页
	page.MustNavigate("https://x.com/home").MustWaitLoad()

	err := rod.Try(func() {
		// 获取内容输入框
		textInput := page.Timeout(10 * time.Second).MustElement(`div.notranslate.public-DraftEditor-content`)
		textInput.MustInput(Content)
		// 检测字符串是否包含标签
		if strings.Contains(Content, "#") {
			_, err := page.Timeout(5 * time.Second).Element(`div.css-175oi2r.r-14lw9ot.r-z2wwpe.r-1upvrn0.r-h3f8nf.r-11yh6sk.r-1rnoaur`)
			time.Sleep(2 * time.Second)
			if err == nil {
				tagBuuton := page.Timeout(5 * time.Second).MustElement(`div.css-175oi2r.r-14lw9ot.r-z2wwpe.r-1upvrn0.r-h3f8nf.r-11yh6sk.r-1rnoaur div[data-testid="typeaheadResult"] button.css-175oi2r.r-x572qd.r-6dt33c.r-1loqt21.r-o7ynqc.r-6416eg.r-1ny4l3l`)
				tagBuuton.MustClick()
				time.Sleep(2 * time.Second)
			}
		}
		// 循环保存图片到本地
		if len(Img) > 0 {
			var file libs.File
			for _, v := range Img {
				tempFile, _ := file.DownloadImage(v)
				// 结束时删除临时文件
				defer os.Remove(tempFile)
				page.MustElement(`input[data-testid="fileInput"]`).MustSetFiles(tempFile)
				time.Sleep(1 * time.Second)
			}
			time.Sleep(5 * time.Second)
		}
	})
	if errors.Is(err, context.DeadlineExceeded) {
		fmt.Println("请求空闲等待超时！")
		return libs.ErrorCode["SendPostFailed"]
	}

	code := postButton(page)
	if code == 200 {
		return libs.ErrorCode["SendPostSuccessful"]
	}
	return libs.ErrorCode["SendPostFailed"]
}

// 发推按钮点击之后监听请求
func postButton(page *rod.Page) int {
	// 定义一个通道接收消息
	router := page.HijackRequests()
	defer router.MustStop()
	ch := make(chan int, 1)
	router.MustAdd("*/CreateTweet*", func(ctx *rod.Hijack) {
		ctx.ContinueRequest(&proto.FetchContinueRequest{})
		ch <- ctx.Response.Payload().ResponseCode
	})

	go router.Run()
	// 点击发布按钮
	postButton := page.Timeout(10 * time.Second).MustElement(`button[data-testid="tweetButtonInline"]`)
	postButton.MustClick()
	select {
	case res := <-ch:
		return res
	case <-time.After(30 * time.Second):
		log.Println("等待上传响应超时")
		return 500
	}
}

// 搜索
func (*TwitterService) Search(accountId int, keyword string, twitterId string) *libs.ErrorInfo {
	// 获取账号状态
	UserService := InitTwitterAccountService()
	user := UserService.GetInfo(int64(accountId))
	if user.LoginStatus != "登录成功" {
		return libs.ErrorCode["AccountHasBeenTakenOffline"]
	}
	// 获取实例
	obj := Browser.GetBrowser(accountId, &libs.Fingerprint{
		Proxy: user.Proxy,
	})
	page := obj.Page
	// 跳转到首页
	page.MustNavigate("https://x.com/home").MustWaitLoad()
	err2 := rod.Try(func() {
		forYou := page.Timeout(10 * time.Second).MustElement(`div[data-testid="ScrollSnap-List"] div.css-175oi2r.r-14tvyh0.r-cpa5s6.r-16y2uox:nth-child(1)`)
		forYou.MustClick()
	})
	if err2 != nil {
	}

	page.MustWaitNavigation()
	// 是否检测到帖子列表
	err := rod.Try(func() {
		page.Timeout(5 * time.Second).MustElement(`article[data-testid="tweet"]`)
	})

	if errors.Is(err, context.DeadlineExceeded) {
		fmt.Println("请求空闲等待超时！")
		// 关闭浏览器
		Browser.CancelBrowser(accountId)
		return libs.ErrorCode["NetworkTimeout"]
	}

	page.MustNavigate("https://x.com/explore").MustWaitLoad()

	searchInput := page.Timeout(10 * time.Second).MustElement(`input[data-testid="SearchBox_Search_Input"]`)
	// 聚焦
	searchInput.Focus()
	searchInput.MustInput(keyword)

	searchCode := waitSearch(page)
	if searchCode != 200 {
		return libs.ErrorCode["SearchFailed"]
	}
	peopleButton := page.Timeout(10 * time.Second).MustElement(`div[data-testid="ScrollSnap-List"] div.css-175oi2r.r-14tvyh0.r-cpa5s6.r-16y2uox:nth-child(3)`)
	peopleButton.MustClick()

	retry, err1 := page.Timeout(5 * time.Second).Element(`div.css-175oi2r.r-1awozwy.r-16y2uox.r-1777fci.r-dd0y9b.r-3o4zer.r-f8sm7e.r-13qz1uu.r-1ye8kvj`)
	if retry != nil || err1 == nil {
		return libs.ErrorCode["SearchFailed"]
	}

	var isSearch bool = true
	var searchCount int = 0
	var activeUser *rod.Element = nil
	var nameArr []string = []string{}
	var nameBool map[string]bool = make(map[string]bool)
	for isSearch && searchCount < 10 {
		searchCount++
		// 获取视口内的所有元素
		ids, err2 := getVisibleElements(page, `div.css-175oi2r.r-f8sm7e.r-13qz1uu.r-1ye8kvj div.css-146c3p1.r-dnmrzs.r-1udh08x.r-1udbk01.r-3s2u2q.r-bcqeeo.r-1ttztb7.r-qvutc0.r-37j5jr.r-a023e6.r-rjixqe.r-16dba41.r-18u37iz.r-1wvb978`)
		if err2 != nil || len(ids) <= 0 {
			return libs.ErrorCode["SearchFailed"]
		}
		for _, v := range ids {
			text := v.MustText()
			if !nameBool[text] {
				nameBool[text] = true
				nameArr = append(nameArr, text)
			}
			if text == "@"+twitterId {
				activeUser = v
				break
			}
		}
		if activeUser != nil {
			isSearch = false
			log.Println("循环：")
			log.Println(searchCount)
			log.Println(len(nameArr))
			log.Println("找到用户")
		} else {
			log.Println("开始滚动")
			scrollElementLocationTop(ids[len(ids)-1])
			time.Sleep(5 * time.Second)
		}
	}

	if searchCount >= 10 {
		return libs.ErrorCode["SearchFailed"]
	}
	time.Sleep(1 * time.Second)
	activeUser.MustClick()
	// 等待5-8秒
	s := 5 + rand.Intn(3)
	time.Sleep(time.Duration(s) * time.Second)
	posts := page.Timeout(10 * time.Second).MustElements(`div.css-175oi2r.r-j5o65s.r-qklmqi.r-1adg3ll.r-1ny4l3l`)
	var postArr []*rod.Element
	for _, post := range posts {
		aid := post.Timeout(10 * time.Second).MustElement(`div.css-146c3p1.r-dnmrzs.r-1udh08x.r-1udbk01.r-3s2u2q.r-bcqeeo.r-1ttztb7.r-qvutc0.r-37j5jr.r-a023e6.r-rjixqe.r-16dba41.r-18u37iz.r-1wvb978`)
		text := aid.MustText()
		if text == "@"+twitterId {
			postArr = append(postArr, post)
		}
	}
	if len(postArr) <= 0 {
		return libs.ErrorCode["SearchSuccessful"]
	}
	// 随机选择一个
	activePost := postArr[rand.Intn(len(postArr))]
	activePost.MustScrollIntoView() // 将元素滑动到页面中间
	tweetText := activePost.Timeout(10 * time.Second).MustElement(`div[data-testid="tweetText"]`)
	// 禁用链接点击
	_, err3 := page.Evaluate(&rod.EvalOptions{
		JS: `(selector) => {
	      const el = document.querySelector(selector);
	      const links = el.querySelectorAll('a');
	      links.forEach(a => {
	          a.style.pointerEvents = 'none';
	      });
	  }`,
		JSArgs: []interface{}{`div[data-testid="tweetText"]`},
	})
	if err3 != nil {
	}
	tweetText.MustClick()
	// 恢复链接的点击行为（如果需要）
	_, _ = page.Evaluate(&rod.EvalOptions{
		JS: `(selector) => {
	      const el = document.querySelector(selector);
	      const links = el.querySelectorAll('a');
	      links.forEach(a => {
	          a.style.pointerEvents = '';
	      });
	  }`,
		JSArgs: []interface{}{`div[data-testid="tweetText"]`},
	})
	// 等待15-20秒
	s2 := 15 + rand.Intn(10)
	time.Sleep(time.Duration(s2) * time.Second)
	// 返回上一页
	// 模拟点击后退按钮
	page.MustNavigateBack()
	// 等待新页面加载完成
	page.MustWaitLoad()
	// 等待5-8秒
	time.Sleep(time.Duration(s) * time.Second)
	return libs.ErrorCode["SearchSuccessful"]
}

// 获取视口内可见的指定元素
func getVisibleElements(page *rod.Page, selector string) ([]*rod.Element, error) {
	// 1. 获取所有候选元素
	elements, err := page.Elements(selector)
	if err != nil {
		return nil, err
	}

	// 2. 过滤出视口内可见的元素
	var visibleElements []*rod.Element
	for _, el := range elements {
		isVisible, err := el.Eval(`function() {
			const rect = this.getBoundingClientRect();
			const viewportHeight = window.innerHeight;
			const viewportWidth = window.innerWidth;
			
			// 判断元素是否至少部分在视口内
			return (
				rect.top < viewportHeight && 
				rect.bottom > 0 && 
				rect.left < viewportWidth && 
				rect.right > 0
			);
		}`)
		if err == nil && isVisible.Value.Bool() {
			visibleElements = append(visibleElements, el)
		}
	}

	return visibleElements, nil
}

// 将指定元素滑动到顶部
func scrollElementLocationTop(el *rod.Element) {
	// 执行JS：滚动到视口顶部（平滑滚动）
	el.MustEval(`function() { 
        this.scrollIntoView({ 
            behavior: "smooth", 
            block: "start" // 顶部对齐
        }); 
    }`)

	// 等待滚动完成
	// time.Sleep(2 * time.Second)
}

// 搜索按钮点击之后监听请求
func waitSearch(page *rod.Page) int {
	// 定义一个通道接收消息
	router := page.HijackRequests()
	defer router.MustStop()
	ch := make(chan int, 1)
	router.MustAdd("*/SearchTimeline*", func(ctx *rod.Hijack) {
		ctx.ContinueRequest(&proto.FetchContinueRequest{})
		ch <- ctx.Response.Payload().ResponseCode
	})

	go router.Run()
	// 点击搜索按钮
	searchInput := page.Timeout(10 * time.Second).MustElement(`input[data-testid="SearchBox_Search_Input"]`)
	searchInput.MustKeyActions().Press(input.Enter).MustDo()
	select {
	case res := <-ch:
		return res
	case <-time.After(30 * time.Second):
		log.Println("等待上传响应超时")
		return 500
	}
}

// 获取指定接口的响应参数
func getApiResponse(page *rod.Page, url string) string {
	// 定义一个通道接收消息
	ch := make(chan string)
	go page.EachEvent(func(e *proto.PageLoadEventFired) {
		log.Println("1234567890")
	}, func(e *proto.NetworkResponseReceived) {
		if strings.Contains(e.Response.URL, url) {
			reply, err := (proto.NetworkGetResponseBody{RequestID: e.RequestID}).Call(page)
			if err != nil {
				fmt.Println(err)
			}
			ch <- reply.Body
			// fmt.Println(reply.Body)
		}
	})()

	select {
	case res := <-ch:
		return res
	case <-time.After(30 * time.Second):
		log.Println("等待上传响应超时")
		return ""
	}
}

func (*TwitterService) LoopViewPost(id int) *libs.ErrorInfo {
	UserService := InitTwitterAccountService()
	user := UserService.GetInfo(int64(id))
	obj := Browser.GetBrowser(id, &libs.Fingerprint{
		Proxy: user.Proxy,
	})
	page := obj.Page
	// 获取推文列表
	postList := InitTwitterPostService().GetAll()
	if len(postList) <= 0 {
		return libs.ErrorCode["NoPostsToView"]
	}
	for _, v := range postList {
		page.MustNavigate(v.Link).MustWaitLoad()
		page.MustWaitNavigation()
		page.MustWaitLoad() // DOM 加载完成
		page.MustWaitIdle() // 基本静止（减少早期误判）
		page.MustActivate() // 前置
		// 等待5-10秒
		s := 5 + rand.Intn(5)
		time.Sleep(time.Duration(s) * time.Second)
		log.Println("浏览推文链接：", v.Link)

		if v.ContentLink != "" {
			page.MustNavigate(v.ContentLink).MustWaitLoad()
			page.MustWaitNavigation()
			page.MustWaitLoad() // DOM 加载完成
			page.MustWaitIdle() // 基本静止（减少早期误判）
			page.MustActivate() // 前置
			// 等待5-10秒
			s2 := 5 + rand.Intn(5)
			time.Sleep(time.Duration(s2) * time.Second)
			log.Println("浏览推文内容链接：", v.ContentLink)
		}
	
	}
	return libs.ErrorCode["ViewSuccessful"]
}
